我想在将控制权交还给webEnumerator.moveNext之前完成executeQueryAsync吗?
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”应该是这样的,
Loop 1
Loop 2
Loop 1
Loop 2
答案 0 :(得分:1)
JavaScript I / O通常是非阻塞的。
context.executeQueryAsync
立即返回,因此它不断迭代原始循环。它接受完成后的回调。
你想要的是同步它。允许的一个概念是Promises。既然你已经用jQuery标记了它,你可以使用它的实现(或者更好,像Bluebird承诺的那样强大)并执行类似的操作:
// 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#reduce
支持这种迭代形式,但我不想添加另一个库。
上面的代码将按顺序运行,如果你想检查它什么时候完成 - 它会返回一个promise本身。所以你可以做onGetSubwebsSuccess(...).then(function(){ /* done here */ });
答案 1 :(得分:0)
由于可以使用以下语法使用单个查询请求网络媒体资源(Web.AllProperties):
clientContext.load(webs,'Include(Url,AllProperties)');
不需要使用executeQueryAsync
方法执行任何后续异步请求,以便为每个网站加载网络媒体资源。
以下示例演示如何从子网站加载Web属性并将其保存到websProps
数组中:
(function(){
var ctx = SP.ClientContext.get_current();
var webs = ctx.get_web().get_webs();
var websProps = {};
ctx.load(webs,'Include(Url,AllProperties)'); //Note: Explicitly specify which properties to load for Web
ctx.executeQueryAsync(function(){
var e = webs.getEnumerator();
while (e.moveNext()) {
var web = e.get_current();
var webUrl = web.get_url();
var props = web.get_allProperties();
var propNameValues = props.get_fieldValues();
//save properties
//Note: For demonstration purposes vti_defaultlanguage property is saved, change it to your property name
websProps[webUrl] = {'DefaultLanguage': propNameValues['vti_defaultlanguage']};
}
console.log(JSON.stringify(websProps));
},
function(sender, args){
//Handle error
}
);
})();