等待多个承诺被拒绝
Wait for multiple promises to be rejected
做一些测试,我需要等待几个 promise 被拒绝。
我知道我可以使用 jQuery.when() 来等待几个 promise 被解决。但是一旦其中一个承诺失败,该方法就会拒绝主承诺。
我知道我所有的承诺都会落空,但无论如何我都需要等待。我该怎么做?
在一种伪代码中我想做的是:
var promise1 = connection.doCall();
var promise2 = connection.doCall();
$.when([promise1, promise2]).allOfThemFail(function() {
assertThatSomeProcessWasDoneOnlyOnce()
});
我认为没有内置函数,但您可以轻松实现
var promise1 = connection.doCall();
var promise2 = connection.doCall();
allOfThemFail([promise1, promise2]).always(function () {
assertThatSomeProcessWasDoneOnlyOnce()
});
function allOfThemFail(array) {
var count = 0;
len = array.length, failed = false, deferred = $.Deferred();
$.each(array, function (i, item) {
item.fail(fail).always(always);
})
function always() {
if (++count == len) {
if (failed) {
deferred.reject();
} else {
deferred.resolve();
}
}
}
function fail() {
failed = true;
}
return deferred.promise();
}
使用 Bluebird promise 库,您可以使用 Promise.settle()
等待所有 promises 被解决(例如履行或拒绝),然后您可以简单地查询列表以查看它们是否都被拒绝。
var p1 = connection.doCall();
var p2 = connection.doCall();
Promise.settle([p1, p2]).then(function(results) {
var allRejected = results.every(function(item) {
return item.isRejected();
});
// act on allRejected here
});
这是 settle()
的 jQuery 特定版本:
(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);
});
}
})();
而且,您可以像使用 Bluebird 解决方案一样使用它:
var p1 = connection.doCall();
var p2 = connection.doCall();
$.settle([p1, p2]).then(function(results) {
var allRejected = results.every(function(item) {
return item.isRejected();
});
// act on allRejected here
});
而且,这是一个使用标准 ES6 承诺从头开始构建的 settle()
类型函数。它 returns 一个单一的承诺,当所有其他承诺完成时(无论它们的最终状态如何)。这个超级承诺的解决结果是一个 PromiseInspection
对象数组,您可以在其中查询 isFulfilled()
或 isRejected()
并可以获得 .value()
或 .reason()
.
Promise.isPromise = function(p) {
return p && (typeof p === "object" || typeof p === "function") && typeof p.then === "function";
}
// ES6 version of settle
Promise.settle = function(promises) {
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;
}
};
}
return Promise.all(promises.map(function(p) {
// make sure any values are wrapped in a promise
if (!Promise.isPromise(p)) {
p = Promise.resolve(p);
}
return p.then(function(val) {
return new PromiseInspection(true, val);
}, function(err) {
return new PromiseInspection(false, val);
});
}));
}
并且,您可以像上面一样使用它:
var p1 = connection.doCall();
var p2 = connection.doCall();
Promise.settle([p1, p2]).then(function(results) {
var allRejected = results.every(function(item) {
return item.isRejected();
});
// act on allRejected here
});
做一些测试,我需要等待几个 promise 被拒绝。
我知道我可以使用 jQuery.when() 来等待几个 promise 被解决。但是一旦其中一个承诺失败,该方法就会拒绝主承诺。
我知道我所有的承诺都会落空,但无论如何我都需要等待。我该怎么做?
在一种伪代码中我想做的是:
var promise1 = connection.doCall();
var promise2 = connection.doCall();
$.when([promise1, promise2]).allOfThemFail(function() {
assertThatSomeProcessWasDoneOnlyOnce()
});
我认为没有内置函数,但您可以轻松实现
var promise1 = connection.doCall();
var promise2 = connection.doCall();
allOfThemFail([promise1, promise2]).always(function () {
assertThatSomeProcessWasDoneOnlyOnce()
});
function allOfThemFail(array) {
var count = 0;
len = array.length, failed = false, deferred = $.Deferred();
$.each(array, function (i, item) {
item.fail(fail).always(always);
})
function always() {
if (++count == len) {
if (failed) {
deferred.reject();
} else {
deferred.resolve();
}
}
}
function fail() {
failed = true;
}
return deferred.promise();
}
使用 Bluebird promise 库,您可以使用 Promise.settle()
等待所有 promises 被解决(例如履行或拒绝),然后您可以简单地查询列表以查看它们是否都被拒绝。
var p1 = connection.doCall();
var p2 = connection.doCall();
Promise.settle([p1, p2]).then(function(results) {
var allRejected = results.every(function(item) {
return item.isRejected();
});
// act on allRejected here
});
这是 settle()
的 jQuery 特定版本:
(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);
});
}
})();
而且,您可以像使用 Bluebird 解决方案一样使用它:
var p1 = connection.doCall();
var p2 = connection.doCall();
$.settle([p1, p2]).then(function(results) {
var allRejected = results.every(function(item) {
return item.isRejected();
});
// act on allRejected here
});
而且,这是一个使用标准 ES6 承诺从头开始构建的 settle()
类型函数。它 returns 一个单一的承诺,当所有其他承诺完成时(无论它们的最终状态如何)。这个超级承诺的解决结果是一个 PromiseInspection
对象数组,您可以在其中查询 isFulfilled()
或 isRejected()
并可以获得 .value()
或 .reason()
.
Promise.isPromise = function(p) {
return p && (typeof p === "object" || typeof p === "function") && typeof p.then === "function";
}
// ES6 version of settle
Promise.settle = function(promises) {
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;
}
};
}
return Promise.all(promises.map(function(p) {
// make sure any values are wrapped in a promise
if (!Promise.isPromise(p)) {
p = Promise.resolve(p);
}
return p.then(function(val) {
return new PromiseInspection(true, val);
}, function(err) {
return new PromiseInspection(false, val);
});
}));
}
并且,您可以像上面一样使用它:
var p1 = connection.doCall();
var p2 = connection.doCall();
Promise.settle([p1, p2]).then(function(results) {
var allRejected = results.every(function(item) {
return item.isRejected();
});
// act on allRejected here
});