最近想重新系统地整理一下前端的知识,因此写了这个专栏。我会尽量写一些业务相关的小技巧和前端知识中的重点内容,核心思想。
前言
在之前我们讲过手写promise的实现(点击回顾),但忽略了Promise类上的方法。今天我们就来补全一下。
Promise.all
Promise.all接受一个参数,参数是一个iterable类型。并返回一个新的promise对象。新promise对象的状态会根据iterable中的每一个promise的状态:
- 如果某一个promise的状态reject了。新的promise状态就会转成reject,result是第一个reject的promise的result。
- 如果所有的promise都resolve了,新promise的状态就是fulfilled,result是一个数组,每项对应入参的promise的执行结果。
示例
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values);
});
// expected output: Array [3, 42, "foo"]
手写
class Promise{
//...
all(promiseList){
// 判断入参是否为iterable类型
if (typeof promiseList.forEach === "undefined") {
return new Error('param is not iterable')
}
return new Promise((resolve, reject) => {
for (let i = 0; i < promiseList.length; i++) {
const res = []
let counter = 0
for (let i = 0; i < promiseList.length; i++) {
// 直接利用Promise.resolve处理结果,就不用自己判断类型。
Promise.resolve(promiseList[i]).then(res => {
counter++
res[i] = res
// 当所有都成功了之后执行resolve
if (counter === promiseList.length) {
resolve(res)
}
// 只要有一个抛错了,就执行reject。
}).catch(e => reject(e))
}
}
})
}
}
}
Promise.race
Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
示例
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, 'one');
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'two');
});
Promise.race([promise1, promise2]).then((value) => {
console.log(value);
// Both resolve, but promise2 is faster
});
// expected output: "two"
手写
class Promise{
...
race(promiseList){
// 判断入参是否为iterable类型
if (typeof promiseList.forEach === "undefined") {
return new Error('param is not iterable')
}
let used = false;
return new Promise((resolve, reject) => {
for (let i = 0; i < promiseList.length; i++) {
const res = [];
for (let i = 0; i < promiseList.length; i++) {
// 直接利用Promise.resolve处理结果,就不用自己判断类型。
Promise.resolve(promiseList[i]).then(res => {
// 只要有一个成功了,就执行resolve。
if(!used){
used = true;
resolve(res);
}
// 只要有一个抛错了,就执行reject。
}).catch(e => {
if(!used){
used = true;
reject(e);
}
})
}
}
})
}
}
总结
比起Promise的手写,all和race方法就相对简单多了。思路就是判断用counter记录处理的promise的次数,以及用标识记录某函数执行过没有。希望对大家有所帮助。