如何使webEnumerator.moveNext等待executeQueryAsync查询执行

How to make webEnumerator.moveNext wait until executeQueryAsync query executes

本文关键字:executeQueryAsync 查询 执行 等待 moveNext 何使 webEnumerator      更新时间:2023-09-26

在将控制权交还给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

JavaScript I/O通常是非阻塞的。

context.executeQueryAsync立即返回,因此它不断迭代原始循环。它在完成时接受回调。

你想要的是同步它。一个允许同步的概念是Promises。由于您已经用jQuery标记了这一点,您可以使用它的实现(或者更好的是,像Bluebird promise这样的强大实现)并执行以下操作:

// 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的这种形式的迭代,但我不想添加另一个库。

上面的代码将按顺序运行,如果你想检查它何时完成——它本身会返回一个promise。所以您可以执行onGetSubwebsSuccess(...).then(function(){ /* done here */ });

由于Web属性(Web.AllProperties)可以使用单个查询请求,使用以下语法:

clientContext.load(webs,'Include(Url,AllProperties)');

不需要使用CCD_ 4方法执行任何后续异步请求来加载每个web的web属性。

以下示例演示了如何从子站点加载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
    }
  );
})();
相关文章:
  • 没有找到相关文章