一步步实现 Promises/A+ 规范 -- 系列三
2019年06月05日预计阅读需要 6 分钟
一步步实现 Promises/A+ 规范 -- 系列
catch 实现
上一篇文章实现了 Promises/A+ 规范中对 then
方法的要求,实现了 then
链的调用逻辑。本篇文章将实现 catch
方法、all
方法、resolve
方法、reject
方法
then 链的缺失参数调用
首先验证如下代码
new Promise((resolve, reject) => {
resolve("success");
}).then(
res => res + ' (promise res)',
).then(
null, // 未传成功回调
err => err + ' (self then err)',
).then(
res => console.log(res),
err => console.log(err)
)
// 输出
// success (promise res)
由此看出不传参数不影响后续调用,且把之前的结果传递给后续方法。修改 then 方法如下
then(onFulfilled, onRejected) {
return new Promise((resolve, reject) => {
// onFulfilled 不是 function 时设置默认方法
if (typeof onFulfilled !== "function") {
onFulfilled = res => res;
}
this.onFulfilledCallbacks.push(() => {
try {
const res = onFulfilled(this.value);
if (res instanceof Promise) {
res.then(resolve, reject);
} else {
resolve(res);
}
} catch (error) {
reject(error);
}
});
// onRejected 不是 function 时设置默认方法
if (typeof onRejected !== "function") {
onRejected = err => {
throw new Error(err instanceof Error ? err.message : err);
};
}
this.onRejectedCallbacks.push(() => {
try {
const res = onRejected(this.reason);
if (res instanceof Promise) {
res.then(resolve, reject);
} else {
resolve(res);
}
} catch (error) {
reject(error);
}
});
})
}
catch 实现原理
catch
的实现其实就是 then
方法没有传第一个参数,只传了第二个参数,这也就是为什么需要先实现上边的逻辑。具体实现:
catch(onRejected) {
return this.then(null, onRejected);
}
Promise.all() 实现
Promise.all
接收一个promise
对象的数组作为参数-
当这个数组里的所有
promise
对象全部变为resolve
,则执行then
中的onFulfilled
- onFulfilled 方法接收一个数组作为参数,这个数组即
promise
对象数组的所有结果,顺序保持一致
- onFulfilled 方法接收一个数组作为参数,这个数组即
- 有一个变为
reject
,则执行then
中的onRejected
// 验证代码一
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(100);
}, 1000)
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(200);
}, 500)
})
Promise.all([promise1, promise2]).then(
res => console.log(res)
)
// 输出 [ 100, 200 ] 顺序与传入相同
// -----------------
// 验证代码二
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(100);
}, 1000)
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject(200);
}, 500)
})
Promise.all([promise1, promise2]).then(
res => console.log(res),
err => console.log(err)
)
// 输出 200
返回一个 promise
all
方法需要和 then
方法一样返回一个 promise
,但 all
方法属于类中的静态方法,其调用方式是直接通过类来调用:Promise.all()
,代码实现
static all(promiseAry = []) {
return new Promise((resolve, reject) => {
})
}
返回一个 prmise
后,该方法就可以链式调用
监控所有 promise 执行状态
每一个 promise 实例的状态可以通过添加 then 方法进行判断,实现如下
static all(promiseAry = []) {
return new Promise((resolve, reject) => {
// 记录 promise 完成个数
let finishNum = 0;
// 返回结果
let result = [];
const len = promiseAry.length;
for (let i = 0; i < len; i++) {
// 对每一个 promise 实例增加 then 方法,监控状态
promiseAry[i].then(val => {
finishNum++;
result[i] = val; // 保证结果与传入顺序一致
if (finishNum === len) {
resolve(result);
}
}, reject)
}
})
}
Promise.resolve() 实现
static resolve(arg) {
return new Promise(function(resolve){
resolve(arg);
});
}
Promise.reject() 实现
static reject(arg) {
return new Promise(function(resolve, reject){
reject(arg);
});
}
到此,就实现了 Promise/A+ 规范,可查看源码