问题描述
我正在尝试为 Promise.all 编写一个 polyfill,当我在没有 setTimeout 的情况下传递承诺时它工作正常,但是使用 setTimeout,我没有得到正确的结果,因为它在计时器到期之前解析并返回了承诺。
如何处理这种情况以在下面的函数中工作,与实际的 Promise.all 工作方式相同。
const promise1 = new Promise((resolve,reject) => {
setTimeout(() => resolve("success 1"),2000);
});
const promise2 = new Promise((resolve,reject) => {
resolve("success 2");
});
const promise3 = new Promise((resolve,reject) => {
resolve("success 3");
});
function resolveAll(promiseArr) {
let arr = [];
return new Promise((resolve,reject) => {
promiseArr.map((each_promise,index) => {
return each_promise
.then((res) => {
arr[index] = res;
if (index === promiseArr.length - 1) {
resolve(arr);
}
})
.catch((err) => {
reject(err);
});
});
});
}
resolveAll([promise1,promise2,promise3])
.then((res) => {
console.log(res,"result");
})
.catch((err) => console.log(err,"error"));
实际结果:[undefined,"success 2","success 3"]
预期结果:["success 1","success 3"]
https://codesandbox.io/s/fast-bush-6osdy?file=/src/index.js
解决方法
你的问题是
if (index === promiseArr.length - 1) {
resolve(arr);
}
只检查最后一个承诺是否已解决,但在您的场景中,第一个承诺是最后一个因 setTimeout 而得到解决的承诺。
一种解决方案是记录已解决的承诺数量,例如
const promise1 = new Promise((resolve,reject) => {
setTimeout(() => resolve("success 1"),2000);
});
const promise2 = new Promise((resolve,reject) => {
resolve("success 2");
});
const promise3 = new Promise((resolve,reject) => {
resolve("success 3");
});
function resolveAll(promiseArr) {
let arr = [],errorMsg = [],resolvedPromiseCount = 0;
return new Promise((resolve,reject) => {
promiseArr.map((each_promise,index) => {
return each_promise.then((res) => {
console.log(res)
arr[index] = res;
resolvedPromiseCount++;
if (resolvedPromiseCount === promiseArr.length) {
resolve(arr);
}
})
.catch((err) => {
resolvedPromiseCount++;
errorMsg.push(err);
});
});
});
}
resolveAll([promise1,promise2,promise3]).then((res) => {
console.log(res,"result");
})
.catch((err) => console.log(err,"error"));