手写函数实现
# 1. 美团:手写 Promise.all
示例:
const p1 = Promise.resolve(3);
const p2 = new Promise(resolve => {
setTimeout(resolve, 1000, 9);
})
const p3 = Promise.resolve(5);
const p4 = 2;
const p = myPromiseAll([p1,p2,p3,p4]);
p.then(res => console.log(res));
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
输出:
[3, 9, 5, 2]
1
思路:
Promise.all 返回一个新的 Promise 实例,该实例在 iterable 参数内所有的 Promise 都“完成(resolved)”或参数中不包含 Promise 时回调完成(resolve);如果参数中 Promise 有一个失败(rejected),此新的 Promise 实例回调失败(reject),失败的原因是第一个失败 Promise 的结果。
因此我们首先将传入的迭代器改为数组以获得其长度,然后遍历数组,对每个元素进行 Promise.resolve 包装,然后通过 .then 和 .catch 判断每个方法的状态。
function myPromiseAll(list) {
const arr = Array.from(list);
const len = arr.length;
const ans = new Array(len);
let cnt = 0;
return new Promise((resolve, reject) => {
for (const i in arr) {
const p = Promise.resolve(arr[i]);
p.then(res => {
ans[i] = res;
cnt++;
if (cnt === len) {
resolve(ans);
}
}).catch(err => {
reject(err);
});
}
});
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
注意
这里用 i 和 cnt 而不用 push 是因为 Promise 的执行顺序是不确定的,如果用 push 的话,ans 的顺序就会乱掉。
在 GitHub 中编辑此页 (opens new window)
上次更新于: 2022/11/3 23:25:22