我正在尝试为Promise.all编写一个polyfill,当我在没有setTimeout的情况下传递Promise时,它运行良好,但使用setTimeout时,我没有得到正确的结果,因为它在计时器到期前解析并返回Promise。
如何在下面的函数中处理这种情况,就像实际的Promise.all一样。
下面是我的代码片段和到codesandbox 的链接
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"));
实际结果:[未定义,"成功2","成功3"]
预期结果:["成功1","成功2","失败3"]
https://codesandbox.io/s/fast-bush-6osdy?file=/src/index.js
您的问题是
if (index === promiseArr.length - 1) {
resolve(arr);
}
只是检查最后一个promise是否已解析,但在您的场景中,第一个promise是由于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"));