Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I want executeQueryAsync to complete before giving back control to webEnumerator.moveNext, anyway ?

function onGetSubwebsSuccess(sender, args) {
    var webEnumerator = webCollection.getEnumerator();

    while (webEnumerator.moveNext()) {
        alert("Loop 1");
        web = webEnumerator.get_current();
        this.props = web.get_allProperties();
        context.load(this.props);
        context.executeQueryAsync(Function.createDelegate(this, gotProperty), Function.createDelegate(this, failedGettingProperty));
    }
}

function gotProperty() {
    var myPropBag = this.props;
    alert("Loop 2");
}

What's happening now is, I get alert for "Loop 1" twice and then alert for "Loop 2" when it should be like this,

Loop 1
Loop 2
Loop 1
Loop 2
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
184 views
Welcome To Ask or Share your Answers For Others

1 Answer

JavaScript I/O is usually non blocking.

context.executeQueryAsync returns immediately, so it keeps iterating the original loop. It accepts a callback for when it's done.

What you want is to synchronize it. One concept that allows that is Promises. Since you already tagged this with jQuery, you can use its implementation (or better, a strong one like Bluebird promises) and do something like:

// promisify executing the query in a context
function execute(context){
    var d = $.Deferred();
    context.executeQueryAsync(function(v){ return d.resolve(v)},
                              function(e){ return d.reject(v)});
    return d.promise();
}

function onGetSubwebsSuccess(sender, args) {
    var webEnumerator = webCollection.getEnumerator();
    return $.when(1).then(function iterate(){ // start an empty promise
         if(!webEnumerator.moveNext()) return ; // done iterating
         alert("Loop 1"); // console.log is better for this though
         var web = webEnumerator.get_current();
         var props = web.get_allProperties();
         context.load(this.props);
         return execute(context).then(function (result){
              alert("Loop 2");
              alert(result); // do whatever you want with the result of the query
              return iterate(); // loop
         });
    });
}

This can get a lot simpler using a stronger promise library like Bluebird which supports this form of iteration using Promise#reduce in the first place, but I didn't want to add another library.

The code above will run in sequence, if you want to check when it's done - it returns a promise itself. So you can do onGetSubwebsSuccess(...).then(function(){ /* done here */ });


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...