手写函数实现
# 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