如何使用 $.when() 获取所有失败回调的结果
How do I get the results of all failed call backs using $.when()
假设我有一个延迟函数:
尝试 1:
$.when(validatePerson(123), validatePerson(456))
.done(function(data) { })
.fail(function(data1, data2) { });
尝试 2:
$.when(validatePerson(123), validatePerson(456))
.done(function(data) { })
.fail(function(data1) { },
function(data2) { });
我想异步进行 2 AJAX 次调用,但在失败时我希望能够确定第一次、第二次或两次调用中的哪一次失败,以便我可以向用户显示适当的错误。
例如
- 验证人 1 (id 123) 失败
- 验证人 2 (id 456) 失败
但我似乎无法让它工作。
尝试1中,data1参数只包含其中一个结果,data2未定义
在尝试 2 中,我使用相同的参数调用了两次回调函数。
$.when()
在您传递的第一个承诺被拒绝时终止。你不能用它得到所有被拒绝的承诺。您可以将它与其他一些代码一起使用来跟踪所有失败。
这里有一个 $.settle()
等待您传递给它的所有承诺被解决或拒绝,returns 一个 PromiseInspection 对象数组,您可以从中判断哪些已解决,哪些已拒绝,以及它们的内容已解决的值或被拒绝的原因是:
(function() {
function isPromise(p) {
return p && (typeof p === "object" || typeof p === "function") && typeof p.then === "function";
}
function wrapInPromise(p) {
if (!isPromise(p)) {
p = $.Deferred().resolve(p);
}
return p;
}
function PromiseInspection(fulfilled, val) {
return {
isFulfilled: function() {
return fulfilled;
}, isRejected: function() {
return !fulfilled;
}, isPending: function() {
// PromiseInspection objects created here are never pending
return false;
}, value: function() {
if (!fulfilled) {
throw new Error("Can't call .value() on a promise that is not fulfilled");
}
return val;
}, reason: function() {
if (fulfilled) {
throw new Error("Can't call .reason() on a promise that is fulfilled");
}
return val;
}
};
}
// pass either multiple promises as separate arguments or an array of promises
$.settle = function(p1) {
var args;
if (Array.isArray(p1)) {
args = p1;
} else {
args = Array.prototype.slice.call(arguments);
}
return $.when.apply($, args.map(function(p) {
// make sure p is a promise (it could be just a value)
p = wrapInPromise(p);
// Now we know for sure that p is a promise
// Make sure that the returned promise here is always resolved with a PromiseInspection object, never rejected
return p.then(function(val) {
return new PromiseInspection(true, val);
}, function(reason) {
// convert rejected promise into resolved promise by returning a resolved promised
// One could just return the promiseInspection object directly if jQuery was
// Promise spec compliant, but jQuery 1.x and 2.x are not so we have to take this extra step
return wrapInPromise(new PromiseInspection(false, reason));
});
})).then(function() {
// return an array of results which is just more convenient to work with
// than the separate arguments that $.when() would normally return
return Array.prototype.slice.call(arguments);
});
}
// simpler version that just converts any failed promises
// to a resolved value of what is passed in, so the caller can just skip
// any of those values in the returned values array
// Typically, the caller would pass in null or 0 or an empty object
$.settleVal = function(errorVal, p1) {
var args;
if (Array.isArray(p1)) {
args = p1;
} else {
args = Array.prototype.slice.call(arguments, 1);
}
return $.when.apply($, args.map(function(p) {
p = wrapInPromise(p);
return p.then(null, function(err) {
return wrapInPromise(errorVal);
});
}));
}
})();
用法:
$.settle(arrayOfPromises).then(function(results) {
// results is an array of PromiseInspection objects and you can
// tell which are resolved and which are rejected
results.forEach(function(item, index) {
if (item.isFulfilled()) {
console.log("promise #" + index + " is fulfilled with value: ", item.value(););
} else {
console.log("promise #" + index + " is rejected with reason: ", item.reason(););
}
});
});
假设我有一个延迟函数:
尝试 1:
$.when(validatePerson(123), validatePerson(456))
.done(function(data) { })
.fail(function(data1, data2) { });
尝试 2:
$.when(validatePerson(123), validatePerson(456))
.done(function(data) { })
.fail(function(data1) { },
function(data2) { });
我想异步进行 2 AJAX 次调用,但在失败时我希望能够确定第一次、第二次或两次调用中的哪一次失败,以便我可以向用户显示适当的错误。
例如
- 验证人 1 (id 123) 失败
- 验证人 2 (id 456) 失败
但我似乎无法让它工作。 尝试1中,data1参数只包含其中一个结果,data2未定义
在尝试 2 中,我使用相同的参数调用了两次回调函数。
$.when()
在您传递的第一个承诺被拒绝时终止。你不能用它得到所有被拒绝的承诺。您可以将它与其他一些代码一起使用来跟踪所有失败。
这里有一个 $.settle()
等待您传递给它的所有承诺被解决或拒绝,returns 一个 PromiseInspection 对象数组,您可以从中判断哪些已解决,哪些已拒绝,以及它们的内容已解决的值或被拒绝的原因是:
(function() {
function isPromise(p) {
return p && (typeof p === "object" || typeof p === "function") && typeof p.then === "function";
}
function wrapInPromise(p) {
if (!isPromise(p)) {
p = $.Deferred().resolve(p);
}
return p;
}
function PromiseInspection(fulfilled, val) {
return {
isFulfilled: function() {
return fulfilled;
}, isRejected: function() {
return !fulfilled;
}, isPending: function() {
// PromiseInspection objects created here are never pending
return false;
}, value: function() {
if (!fulfilled) {
throw new Error("Can't call .value() on a promise that is not fulfilled");
}
return val;
}, reason: function() {
if (fulfilled) {
throw new Error("Can't call .reason() on a promise that is fulfilled");
}
return val;
}
};
}
// pass either multiple promises as separate arguments or an array of promises
$.settle = function(p1) {
var args;
if (Array.isArray(p1)) {
args = p1;
} else {
args = Array.prototype.slice.call(arguments);
}
return $.when.apply($, args.map(function(p) {
// make sure p is a promise (it could be just a value)
p = wrapInPromise(p);
// Now we know for sure that p is a promise
// Make sure that the returned promise here is always resolved with a PromiseInspection object, never rejected
return p.then(function(val) {
return new PromiseInspection(true, val);
}, function(reason) {
// convert rejected promise into resolved promise by returning a resolved promised
// One could just return the promiseInspection object directly if jQuery was
// Promise spec compliant, but jQuery 1.x and 2.x are not so we have to take this extra step
return wrapInPromise(new PromiseInspection(false, reason));
});
})).then(function() {
// return an array of results which is just more convenient to work with
// than the separate arguments that $.when() would normally return
return Array.prototype.slice.call(arguments);
});
}
// simpler version that just converts any failed promises
// to a resolved value of what is passed in, so the caller can just skip
// any of those values in the returned values array
// Typically, the caller would pass in null or 0 or an empty object
$.settleVal = function(errorVal, p1) {
var args;
if (Array.isArray(p1)) {
args = p1;
} else {
args = Array.prototype.slice.call(arguments, 1);
}
return $.when.apply($, args.map(function(p) {
p = wrapInPromise(p);
return p.then(null, function(err) {
return wrapInPromise(errorVal);
});
}));
}
})();
用法:
$.settle(arrayOfPromises).then(function(results) {
// results is an array of PromiseInspection objects and you can
// tell which are resolved and which are rejected
results.forEach(function(item, index) {
if (item.isFulfilled()) {
console.log("promise #" + index + " is fulfilled with value: ", item.value(););
} else {
console.log("promise #" + index + " is rejected with reason: ", item.reason(););
}
});
});