具有多个SharePoint CAML查询的jQuery Deferred / Promises

时间:2016-01-19 04:02:51

标签: jquery sharepoint promise deferred caml

大家好我从三个单独的SharePoint列表中有三个异步调用,每个查询都有一个返回对象和数组的成功回调。我希望在所有三个成功回调返回后执行另一个函数。我不知道如何使用jQuery deferreds。我的代码如下。请帮助我了解如何使用延迟来实现上述目标。

function managementMain() {
    //From here I want to call the third function after executing 
      the managementQuery function.
      outPutObj = managementQuery();
    //Execute some third function with outPutObj:
    third function(outPutObj);
}
function managementQuery() {
    //CAML definition 1 here.
    clContext.executeQueryAsync(Function.createDelegate(this, function () { var soObj = onSOQuerySucceeded(); }), Function.createDelegate(this, this.onQueryFailed));
    //CAML definition 2 here.
    clContext.executeQueryAsync(Function.createDelegate(this, function () { var poObj = onPOQuerySucceeded(); }), Function.createDelegate(this, this.onQueryFailed));
   //CAML definition 3 here.
   clContext.executeQueryAsync(Function.createDelegate(this, function () { var salesRepNamesList = onSalesRepNamesQuerySucceeded(); }), Function.createDelegate(this, this.onQueryFailed));
   return {
       soObj: soObj,
       poObj: poObj,
       salesRepList: salesRepNamesList
   }
}
function onSOQuerySucceeded() {
     //Do something with the SharePoint List and return an object called soObj.
}
function onSalesRepNamesQuerySucceeded() {
     //Do something with the SharePoint List and return an array called salesRepNames.
}
function onPOQuerySucceeded() {
     //Do something with the SharePoint List and return an object called poObj.
}

我遇到的问题是soObj,poObj和salesRepNamesList可能不会被返回 managementQuery函数返回。因此,执行第三个函数的时间可能会定义outPutObj。请指教。感谢。

2 个答案:

答案 0 :(得分:1)

首先,代码比它需要的更复杂:

  • 您可以清除Function.createDelegate(),这是(a)非标准javascript,(b)没有必要,因为它所应用的所有功能都不使用this。微软有点顽皮,包括Function.createDelegate()在他们的例子中,因为它似乎与使用clientContext.executeQueryAsync()密切相关,但事实并非如此。
  • 按照惯例,带有Async后缀的方法应该返回一个promise,这样就不需要创建/解析你自己的Deferreds了。但是,微软再次有点调皮,因为clientContext.executeQueryAsync() 没有遵循惯例。

其次,在不首先聚合传递数据的承诺的情况下,不能聚合异步导出的数据。如上所述,问题中的代码缺少任何承诺汇总。由于这是jQuery,我们希望在代码中的某处看到jQuery.when()

关于promisification,最好的方法总是在最低级别进行promisify - 在这种情况下为clientContext.executeQueryAsync()编写一个可重用的适配器函数,它返回所需的promise。这将允许更高级别的函数managementQuery()大大简化。

这里是promisifier:

clContext.executeQueryAsync_ = function() {
    return $.Deferred(function(dfrd) {
        clContext.executeQueryAsync(function(sender,args) {
            dfrd.resolve({'sender':sender, 'args':args});
        }, function(sender,args) {
            dfrd.reject({'sender':sender, 'args':args})
        });
    }).promise();
};

现在,managementQuery()可以写成没有延迟而没有Function.createDelegate(),如下所示:

function managementQuery() {
    var query = clContext.executeQueryAsync_;  // If clContext.executeQueryAsync() returns a promise, then assign clContext.executeQueryAsync() instead.
    var promise1 = query(/* so params */);
    var promise2 = query(/* po params */);
    var promise3 = query(/* salesRep params */);

    // Now aggregate the three promises with $.when(), and chain .then() to handle the delivered data.
    return $.when(promise1, promise2, promise3)
    .then(function(soObj, poObj, salesRepObj) {
        // soObj, poObj and salesRepObj each have .sender and .args properties.
        // Now the required object can be created and returned 
        // to become the data delivered (in a promise) by managementQuery().
        return {
            'soObj': onSOQuerySucceeded(),
            'poObj': onPOQuerySucceeded(),
            'salesRepList': onSalesRepNamesQuerySucceeded()
        };
    });
}

managementMain()可以写成如下:

function managementMain() {
    return managementQuery()
    .then(someOtherFunction) // someOtherFunction will be automagically passed the object created/returned above.
    .fail(function(e) {
        // Any promise rejection in managementQuery() or someOtherFunction will end up here.
        console.log(e);
        this.onQueryFailed();
    });
}

答案 1 :(得分:0)

你基本上会创建3个延迟对象,每个异步请求一个。完成异步请求后,您将在延迟对象上调用.resolve方法

// query will return a promise
outputPromise = query();

// your third function needs to wait for the promise to resolve
// to ensure the wait, you use the .then() method on the promise above
outputPromise.then(function(outputObj) {
    thirdFunction(outputObj);
});

function query() {
    // Create deferred objects
    var deferred1 = $.Deferred();
    var deferred2 = $.Deferred();

    clContext.executeQueryAsync(Function.createDelegate(this, function () { 
        var soObj = onSOQuerySucceeded();
        deferred1.resolve(soObj);
    }), Function.createDelegate(this, function () {
        this.onQueryFailed();
        deferred1.reject();
    }));

    clContext.executeQueryAsync(Function.createDelegate(this, function () { 
        var poObj = onPOQuerySucceeded();
        deferred2.resolve(poObj);
    }), Function.createDelegate(this, function() {
        this.onQueryFailed();
        deferred2.reject();
    }));

    // we must wait for all async ops to finish. to do this, we use the $.when() method
    // the $.when() method returns a promise that is resolved with the return
    // values of each deferred that was passed in. the then takes a callback
    // function and will spread each resolved value over the callback function's arguments
    return $.when(deferred1, deferred2).then(function(soObj, poObj) {
       // create the output object in the format you specified
       return {
           soObj: soObj,
           poObj: poObj
       }
    });
}

jQ Deferred docs在这里:https://api.jquery.com/category/deferred-object/如果您需要查找某些内容

作为旁注,我强烈建议使用另一个Promise库,如bluebird或Q而不是jQuery的延迟。它们符合广泛接受的Promise/A+规范以及随后的ES2015 Promise规范。 jQ 3将延迟承诺/ A +,但延迟模式不在ES2015中,你应该使用其他库提供的Promise模式。