Search code examples
javascriptarrayssharepointoffice365sharepoint-jsom

Nested context.executeQueryAsync with Deferred


How can I use nested context.executeQueryAsync with Deferred? Below is my code and I will explain what exactly I am looking for:

Code

function getValues() {
    var dfd = $.Deferred(function () {

        context.executeQueryAsync(function () {
            var navigationItem = [];

            // First Loop
            while (termEnumerator.moveNext()) {

                // Push Parent Terms in navigationItem array
                navigationItem.push({ "name": ""});

                // Get Sub Terms
                context.executeQueryAsync(function () {
                    // Second Loop
                    while (termsEnum.moveNext()) {
                       // Push Sub Terms in navigationItem array
                        navigationItem.push({ "name": ""});
                    }
                }, function (sender, args) {
                    console.log(args.get_message());
                });
            }

            dfd.resolve(navigationItem);

        }, function (sender, args) {
            console.log(args.get_message());
            dfd.reject(args.get_message());
        });
    });
    return dfd.promise();
}

Basically I am trying to fetch Taxonomy (Terms & it's sub terms) in SharePoint Online using above code structure. Initially I have created an array named navigationItem and iterating through all the terms.

During iteration, first of all, I am pushing terms into this array and along with this, I am also getting it's sub terms if any and pushing it into the same array.

I want that code doesn't execute further until second loop completes it's execution. So that I will have final array while returning it to another function.


Solution

  • I want that code doesn't execute further until second loop completes it's execution. So that I will have final array while returning it to another function.

    In this case, you need to have a defer for each executeQueryAsync.

    Then, you need a create an overall defer to wait all of the async methods finished.

    Here is the sample code for your reference:

    (function ($) {
        function executeQueryAsync(succeededCallback, failedCallback)
        {
            var period = Math.random() * 10000;
    
            setTimeout(function () {
                succeededCallback();
            }, period);
    
        }
    
        function forEachAsync(items, funcAsync, callback)
        {
            var count = 0;
    
            var total = $.Deferred();
    
            function increment()
            {
                count++;
    
                if(count == items.length)
                {
                    total.resolve();
                }
            }
    
            for (var i = 0; i < items.length; i++)
            {
                (function exec(item) {
                    var deferred = $.Deferred(function (defer) {
                        funcAsync(function () {
                            callback();
                            defer.resolve();
                        });
                    });
    
                    deferred.done(function () {
                        increment();
                    });
                })(items[i]);
            }
    
            return total.promise();
        }
    
        var promise = forEachAsync([1, 2, 3, 4, 5], executeQueryAsync, function () {
            console.log('call back executing + ' + Date.now());
        });
    
        promise.done(function () {
            console.log("promise done");
        });
    })(jQuery); 
    

    enter image description here