这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战
前面写了 Promise的入门和相关方法的使用, Promise的关键问题, 手写Promise核心原理(一), 需要的童鞋请移步。这篇文章写下Promise相关方法的核心原理:
一、手写Promise.prototype.then()
我们知道then方法的作用是分别指定resolve和reject的回调函数,返回一个新的Promise实例。
(不了解的请翻看之前的文章Promise的入门和相关方法的使用)
then方法内部具体有哪些操作呢?
- 接收的参数为resolve回调函数和reject回调函数,指定回调函数的默认值。
- 返回一个新的promise实例。
- 根据promise实例当前不同的状态调用不同的回调函数。
- 将回调函数的结果绑定到新的promise上去。 前两个操作是比较简单的:
- 第一个操作为接收两个参数,所以我们只需给then方法设置两个形参onResolved和onRejected。
- 第二个操作是返回一个新的Promise实例,所以在then方法中直接return new Promise。 第三四个操作相对复杂些,需要展开分析:
- 第三个操作是根据不同的状态调用不同的回调函数,promise实例的当前状态总共有三种可能性:pending、fulfilled、rejected。 (1)当状态为fulfilled时,调用onResolved回调函数;
(2)当状态为rejected时,调用onRejected回调函数;
(3)当状态为pending时,要将onResolved和onRejected两个回调函数一起传入callbacks数组中,等待后续调用执行。
- 第四个操作将回调函数执行后的结果绑定到新的Promise上,这里由于无论哪种状态都要做这个处理,所以我们封装成一个handler方法,减少重复代码。由于要将返回结果绑定到新的promise上,所以要将handler方法写在该Promise中。回调函数执行的过程中可能会出现异常,所以使用try/catch捕获异常。回调函数的执行结果分为以下三类,分别对应不同的返回结果:
(1)抛出异常,返回promise的结果为失败。
(2)返回的是promise,返回promise的结果就是这个结果。
(3)返回的不是promise,返回promise为成功,value就是返回值。
代码如下:
Promise1.prototype.then = function(onResolved, onRejected) {
var _this = this;
// 指定回调函数的默认值
onResolved = typeof onResolved == "function" ? onResolved : value => value;
onRejected = typeof onRejected == "function" ? onRejected : reason => { throw reason; };
return new Promise1(function(reslove, reject) {
// handler方法的作用:执行回调函数并将返回值分类传递给最后需要返回的promise
function handler(callback) {
try {
var result = callback(_this.data);
if (result instanceof Promise1) {
// 返回的是promise
result.then(resolve, reject);
} else {
// 返回的不是promise
resolve(result);
}
} catch (error) {
// 抛出异常
reject(error);
}
}
if (_this.status == PENDING) {
// pending状态时要把回调函数给存起来,后面状态改变后再调用
_this.callbacks.push({
onResolved(value) {
// 执行后也需要将返回值传给最后要返回的promise
handler(onResolved);
},
onRejected(reason) {
handler(onRejected);
}
});
console.log(_this.callbacks);
} else if (_this.status == FULFILLED) {
handler(onResolved);
} else {
handler(onRejected);
}
});
};