如何使webEnumerator.moveNext等到executeQueryAsync查询执行 [英] How to make webEnumerator.moveNext wait until executeQueryAsync query executes
问题描述
我想在将控制权交还给webEnumerator.moveNext之前完成executeQueryAsync吗?
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");
}
现在发生的是,我两次收到有关循环1"的警报,然后在出现这种情况时发出循环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
推荐答案
JavaScript I/O通常是非阻塞的.
JavaScript I/O is usually non blocking.
context.executeQueryAsync
立即返回,因此它继续迭代原始循环.完成后,它将接受回调.
context.executeQueryAsync
returns immediately, so it keeps iterating the original loop. It accepts a callback for when it's done.
您想要的是对其进行同步.允诺的一个概念就是承诺.既然您已经用jQuery标记了它,则可以使用它的实现(或者更好的是像Bluebird promises这样的强大实现)并执行以下操作:
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
});
});
}
使用像Bluebird这样的更强大的Promise库,它可以变得更加简单,该库首先使用Promise#reduce
支持这种形式的迭代,但是我不想添加其他库.
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.
如果您想检查完成时间,上面的代码将按顺序运行-它本身返回一个promise.所以你可以做onGetSubwebsSuccess(...).then(function(){ /* done here */ });
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 */ });
这篇关于如何使webEnumerator.moveNext等到executeQueryAsync查询执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!