如何等待几个 HTTP 承诺完成,并且仅在所有承诺都失败时才显示模式



我在一个页面上有两个HTTP调用,它们完全是分开的。

vm.$onInit = function() {
....
....
//Get all the items only once during initialization
ds.getAllItems().then(function(result){
vm.items = result;
},function(error){
vm.errorInApi = true;
});
.....
.....
}
vm.getTimes = function(){
.....
.....
HttpWrapper.send(url,{"operation":'GET'}).then(function(times){
.....
}

如果两个 API 都失败,那么我只需要显示一个模态。

我可以将变量启动为 true,并且在 API 失败时,我可以将其设为 false,然后仅显示模态。

但是,等待所有 API 完成需要多长时间?

嗯......简单地颠倒承诺的极性并使用Promise.all()

Promise.all()通常会在所有承诺解决后解决,所以一旦承诺被颠倒,一旦所有承诺都被拒绝,它就会解决......

var invert = p => new Promise((v, x) => p.then(x, v));
Promise.all([Promise.reject("Error 404"), Promise.reject("Error WTF")].map(invert))
.then(v => console.log(v));

因此,根据@guest271314评论,我将解决方案扩展到银勺中,以显示如何将反转承诺应用于此任务。

var invert = p => new Promise((v, x) => p.then(x, v)),
prps   = [Promise.reject("Error 404"), Promise.reject("Error WTF")]; // previously rejected promises
myButton.addEventListener('click', function(e){
setTimeout(function(...p){
p.push(Promise.reject("Error in Click Event Listener"));
Promise.all(p.map(invert))
.then(r => results.textContent = r.reduce((r,nr) => r + " - " + nr));
}, 200, ...prps);
});
<button id="myButton">Check</button>
<p id="results"></p>

如果任何承诺(包括先前获得的承诺或事件处理程序中的一次承诺(被解析,您将不会得到任何输出。

您可以使用async/await.catch()来确定被拒绝Promise的数量,如果数字等于 N,则执行操作,其中 N 是执行操作所需的拒绝Promise值的数量。

正如@trincot所提到的,先决条件是从函数中returnPromise,并从传递给.then()的函数中return一个值,并在.then()的第二个参数处throw.catch()或函数的Error()请参阅为什么在 .then(( 处未定义值链接到 Promise?

const N = 2;
function onInit() {
return Promise.resolve("resolved")
}
function getTimes() {
return Promise.reject("rejected");
}
const first = onInit();
document.querySelector("button")
.onclick = async function() {
let n = 0;
const firstP = await first.catch(() => ++n);
const secondP = await getTimes().catch(() => ++n);
if (n === N) {
// do stuff if `n` is equal to `N`
} else {
// do other stuff
console.log(n, N)
}
};
<button>click</button>

您可以使用Promise.all.

首先,您应该在一个数组中获取两个承诺。为了实现这一点,如果你的两个函数返回它们创建的承诺,它可能很有用:

vm.$onInit = function() {
....
....
return ds.getAllItems().then(function(result){
vm.items = result;
},function(error){
vm.errorInApi = true;
});
}
vm.getTimes = function(){
.....
.....
return HttpWrapper.send(url,{"operation":'GET'}).then(function(times){
.....
});
}

然后,将从返回值构建数组:

var arr = [];
arr.push(vm.$onInit());
...
arr.push(vm.getTimes());

您在评论中写道getTimes"在单击某个按钮时被调用",因此您将在那里进行第二次推送。

或者,也许您看到了另一种在数组中获得这些承诺的方法......你怎么做并不重要,只要你做到这一点。

然后(在该单击处理程序中(您需要检测两个承诺都被拒绝的情况。Promise.all可以做到这一点,但你需要翻转承诺结果:

// Flip promises so that a rejected one is regarded as fulfilled and vice versa:
arr = arr.map(p => p.then(res => { throw res }).catch(err => err));
// Detect that all original promises rejected, i.e. that the new promises all fulfill.
Promise.all(arr).then(function() {
// execute whatever you need to execute when both ajax calls failed
}).catch(err => err); // ignore

最新更新