大家好我从三个单独的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。请指教。感谢。
答案 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模式。