之前的文章介绍了什么是Promise,它是一种更加现代解决JS异步编程的解决方案.现在我们通过了解Promise A+规范,来自己尝试实现一个简单的Promise,加深对它的理解.
一. Promise A+规范
promise:是一个拥有then方法的对象或函数,其行为符合本规范thenable:是一个定义了then方法的对象或函数。这个主要是用来兼容一些老的Promise实现,只要一个Promise实现是thenable,也就是拥有then方法的,就可以跟Promises/A+兼容。value:指reslove出来的值,可以是任何合法的JS值(包括undefined,tenable和promise等)exception:异常,在Promise里面用throw抛出来的值reason:拒绝原因,是reject里面传的参数,表示reject的原因promise必须有三种状态pending、fulfilled和rejectedthen:promise必须提供一个then方法来访问其当前或最终的value或reason,then方法接受两个参数onFulfilled和onRejected
二. 手写Pormise
tip1: 我们在调用promise构造函数时,在合适时机根据状态情况来分别调用executor的两个参数reslove或reject,经过他们的处理后的值,可以在then方法中通过它的两个函数参数获取,resolve的处理后的值在onfulfilled中获取,reject处理后的值则在onrejected中拿到。
tip2: Promise实例的状态只能从pending变为fuilfilled,或从pending变为rejected,状态一旦变更就无法再次变化
tip3:Promise的链式调用,是通过then方法的onfulfilled和onrejected支持返回一个Promise实例或普通值,而且返回的这个Promise实例或普通值将会传给下一个then方法的onfulfilled和onrejected函数
// 首先来创建骨架
function Promise(executor) {
// 因为状态的不可变,需要存储状态
// 用两个值分别存储`resolve`和`reject`处理后的值
this.status = "pending";
this.value = null;
this.reason = null;
// 让resolve可以支持异步,我们要把onfulfilled方法在pending时存起来,在resolve中执行,来实现异步
// 为了支持多个then方法,所以将它们都存起来,依次调用
this.onFulfilledArray = [];
this.onRejectedArray = [];
// 作为executor的参数给开发者使用,下同
const resolve = (value) => {
// 这里通过setTimeout来保证异步执行,但是Promise属于微任务,所以这里是不严谨的
setTimeout(() => {
if (this.status === "pending") {
this.value = value;
// 保证状态只能从pending变化一次
this.status = "fulfilled";
this.onFulfilledArray.forEach((func) => {
func(value);
});
}
});
};
const reject = (reason) => {
setTimeout(() => {
if (this.status === "pending") {
this.reason = reason;
this.status = "rejected";
this.onRejectedArray.forEach((func) => {
func(reason);
});
}
});
};
// 捕获构造函数的错误,并触发Promise实例的状态改变
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
Promise.prototype.then = function (onfulfilled, onrejected) {
// 作为then方法的返回值
let promise2;
if (this.status === "fulfilled") {
return promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
try {
// 新promise2经过resolved处理后的值为onfulfilled的执行结果,下同
let result = onfulfilled(this.value);
resolve(result);
} catch (error) {
reject(error);
}
});
});
}
if (this.status === "rejected") {
return promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
try {
let result = onrejected(this.reason);
resolve(result);
} catch (error) {
reject(error);
}
});
});
}
if (this.status === "pending") {
return promise2 = new Promise((resolve, reject) => {
/**
* Promise调用then方法后应该返回的Promise,就是这里的Promise2
* Promise2应该在异步处理结束后,在依次执行onFulfilledArray和onRejectedArray数组中的函数时被决议
* 同时数组中的函数还应该确定promise2的状态并决议
* 下同
*/
this.onFulfilledArray.push(() => {
try {
let result = onfulfilled(this.value);
resolve(result);
} catch (error) {
reject(error);
}
});
this.onRejectedArray.push(() => {
try {
let result = onrejected(this.value);
resolve(result);
} catch (error) {
reject(error);
}
});
});
}
};
尾言
至此,我们已经基本实现了一个Promise,保证了它的状态不可逆,支持链式调用、完成了then方法。为了实现一份较为完整了Promise,我还是参考、学习了很多相关内容,希望我写的这些,可以为大家提供一些帮助。后续我还会继续深入关于规范中关于The Promise Resolution Procedure的部分,有兴趣的同学,可以一起讨论学习。