Javascript 当(…)不考虑最终状态时,是否有方法检查美元承诺的个人结果
检查以下示例Javascript 当(…)不考虑最终状态时,是否有方法检查美元承诺的个人结果,javascript,jquery,ajax,deferred,Javascript,Jquery,Ajax,Deferred,检查以下示例 $.when(a1, a2, a3, a4, .....) .done(function (){alert('done')}) .fail(function (){alert('fail')}); 如果所有a1 ax都成功,我可以检索和处理“完成”函数中所有“承诺”的所有数据 如果a1和a2失败,而a3和a4成功并返回一些数据。“fail”被调用,并没有说明实际失败的内容,也没有传递成功的值(不传递任何参数) 问题 有没有办法通过“延迟”(即使失败)检
$.when(a1, a2, a3, a4, .....)
.done(function (){alert('done')})
.fail(function (){alert('fail')});
如果所有a1 ax都成功,我可以检索和处理“完成”函数中所有“承诺”的所有数据
如果a1和a2失败,而a3和a4成功并返回一些数据。“fail”被调用,并没有说明实际失败的内容,也没有传递成功的值(不传递任何参数)
问题
有没有办法通过“延迟”(即使失败)检索成功调用(a3和a4)的值(数据),或者我应该为此为每个承诺分配单独的回调?$。when()
被设计为在传递给它的任何承诺被拒绝时立即执行.fail()
。因此,如果a1或a2被拒绝,它将调用.fail()
,并且可能还没有a3和a4的数据。这就是它的设计方式,在某些情况下确实限制了它的实用性。如果您想知道每个单独的结果,而不管其他承诺是否失败,并且您正在使用$.when()
,那么正如您所猜测的,您需要将自己的.done()
和.fail()
处理程序附加到每个单独的承诺
巧合的是,我实现了一个多延迟对象(供我自己使用),它允许您指定如果任何承诺失败(如$.when()
所做的),是希望它立即失败,还是等到所有承诺都达到最终结果后再调用master.fail()
或.done()
。这可能对你有用
这是功能与$之间差异的总结。when()
:
.setFailImmediate(false)
方法完成所有承诺之前不调用自己的.fail()
.add()
方法,因此您可以向它添加更多承诺(在解决之前)。由于这些承诺通常在一个循环中收集,因此只需.add()
一个承诺,而不是将它们全部收集在一个数组中,然后传递给$.when()
.progress()
的工作原理不同。这不会重复每个承诺的.progress()
,而是执行.notify()
,在每个承诺被拒绝或解决时触发.progress()
,以便跟踪每个承诺的完成情况。如果你想要每个承诺的实际进展,你可以直接附加到它们上.getFailYet()
查询延迟的承诺是否已失败.getRemaining()
查询有多少承诺尚未完成$.MultiDeferred()
返回一个实际的延迟对象(添加了一些额外的方法),您还可以对其调用.promise()
,以仅获取promise对象(该对象上也会有额外的方法)
MultiDeferred
对象可以这样使用:
var d = $.MultiDeferred(a1, a2, a3, a4);
// configure it to not fail immediately when any single promise fails
d.setFailImmediate(false);
// you can optionally add more promises here
// often in a loop
d.add(a5, a6);
d.done(function() {
// called when all promises have been successfully resolved
}).fail(function() {
// even if one promise failed, all the data from all the promises
// is passed here as this can be configured to wait for all
// promises to finish before calling .fail()
});
工作演示:
多重延迟对象的代码如下所示:
jQuery.MultiDeferred = function(/* zero or more promises */) {
// make the Deferred
var self = jQuery.Deferred();
// get the promise so new methods can be added to it too
var promise = self.promise();
var remainingToFinish = 0;
// two parallel arrays that contain the promises that are added
// and the arguments passed to reject() or resolve()
// so when we call the master reject() or resolve(), we can pass all those args on through
var promises = [];
var args = [];
// keep track of what to do upon failure and whether we had any failures
var anyFail = false;
var failImmediate = false;
function _add(p) {
// save our index in a local variable so it's available in this closure later
// so we know what the array index was of this particular promise when it fires
var index = promises.length;
// save this promise into our array structure
promises.push(p);
// push placeholder in the args array
args.push([null]);
// one more waiting to finish
++remainingToFinish;
// see if all the promises are done
function checkDone(fail) {
return function() {
anyFail |= fail;
// make copy of arguments so we can save them
args[index] = Array.prototype.slice.call(arguments, 0);
--remainingToFinish;
// send notification that one has finished
self.notify.apply(self, args[index]);
// if all promises are done, then resolve or reject
if (self.state() === "pending" && (remainingToFinish === 0 || (fail && failImmediate))){
var method = anyFail ? "reject" : "resolve";
self[method].apply(self, args);
}
}
}
// add our own monitors so we can collect all the data
// and keep track of whether any fail
p.when(checkDone(false), checkDone(true));
}
self.add = function(/* one or more promises or arrays of promises */) {
if (this.state() !== "pending") {
throw "Can't add to a deferred that is already resolved or rejected";
}
var arg;
for (var i = 0; i < arguments.length; i++) {
// if the next arg is not an array, then put it in an array
// so the rest of the code can just treat it like an array
arg = arguments[i];
if (!Array.isArray(arg)) {
arg = [arg];
}
for (var j = 0; j < arg.length; j++) {
_add(arg[j]);
}
}
return this;
}
// set whether the deferred should reject immediately if any subordinate
// promises fails or whether it should wait until all have completed
// default is to wait until all have completed
self.setFailImmediate = function(failQuick) {
failImmediate = failQuick;
return this;
}
// only query methods are on the promise object
// get count of remaining promises that haven't completed yet
self.getRemaining = promise.getRemaining = function() {
return remainingToFinish;
}
// get boolean on whether any promises have failed yet
self.getFailYet = promise.getFailYet = function() {
return anyFail;
}
// add any promises passed to the constructor
self.add.apply(self, arguments);
return self;
};
jQuery.MultiDeferred=函数(/*零个或多个承诺*/){
//延期交货
var self=jQuery.Deferred();
//获得承诺,这样新方法也可以添加到其中
var promise=self.promise();
var remainingToFinish=0;
//包含添加的承诺的两个并行阵列
//以及传递给reject()或resolve()的参数
//因此,当我们调用master reject()或resolve()时,我们可以通过
var承诺=[];
var args=[];
//跟踪失败后要做什么,以及我们是否有任何失败
var anyFail=false;
var=false;
功能添加(p){
//将索引保存在局部变量中,以便稍后在此闭包中可用
//所以我们知道当它触发时,数组索引是什么
var指数=1.5倍长度;
//将此承诺保存到我们的数组结构中
承诺推送(p);
//在args数组中推送占位符
参数推送([null]);
//还有一个等待完成
++保持完美;
//看看是否所有的承诺都兑现了
功能检查完成(失败){
返回函数(){
anyFail |=失败;
//复制参数以便保存它们
args[index]=Array.prototype.slice.call(参数,0);
--保持完美;
//发送已完成的通知
self.notify.apply(self,args[index]);
//如果所有的承诺都完成了,那么就决定还是拒绝
if(self.state()==“pending”&&(remainingToFinish===0 | |(fail&&failImmediate))){
var method=anyFail?“拒绝”:“解决”;
self[method].apply(self,args);
}
}
}
//添加我们自己的监视器,以便收集所有数据
//并记录是否有任何失败
p、 when(checkDone(false)、checkDone(true));
}
self.add=函数(/*一个或多个承诺或承诺数组*/){
if(this.state()!==“待定”){
抛出“无法添加到已解决或已拒绝的延迟”;
}
var-arg;
for(var i=0;i