如何解决在 Javascript 中为 Promise.all 编写 Polyfill 时如何处理 setTimeout 情况
我正在尝试为 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"));
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。