Promise
js的单线程特性导致大量的异步操作,异步操作我们通常使用函数回调的方式实现。大量的函数回调会产生我们的毁掉地狱,降低代码的可读性和可维护性。
为了解决这些问题,先后出现了Promise函数、Generator函数和async函数。目前Promise配合async/await成为了主流。
Promise本质上并没有改变异步操作,只是让我们可以用同步的代码写法去书写异步操作。增加代码的可读性。
Promise是ES6中确定的,今天我们就使用ES5的写法,手动实现自己的Promise,以求彻底掌握Promise的核心原理。今天我们只封装实现Promise的基本功能。
先看一下在ES6中我们是如何使用Promise的
let promiseFn = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(111)
}, 1000)
});
promiseFn.then(res => {
console.log(res) // res === 111
})
// 使用async/await
async function promiseFn () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(111)
}, 1000)
})
}
let res = await promiseFn() // res === 111
Promise规范
里面详细介绍了Promise的各种术语、定义和规范。其中最需要理解的就是Promise的三种状态以及其中的状态变化。“等待态(Pending)、执行态(Fulfilled)和拒绝态(Rejected)”。
状态改变不可逆,只能Pending --> Fulfilled 或者 Pending --> Rejected
预备
使用status存储Promise状态(pending、fulfilled、rejected)
使用value存储resolve的数据
使用err存储reject的错误信息
使用原型链继承的方式创建then函数
使用onFulfilledArr存储将要执行的resolve函数
使用onRejectedArr存储将要执行的reject函数
创建 MyPromise构造函数
// 创建 MyPromise构造函数
function MyPromise (fn) {
let self = this;
this.value = null; // 存储resolve数据
this.status = 'pending'; // 存储状态
this.err = null; // 存储reject错误信息
this.onFulfilledArr = []; // 存储将要执行的resolve函数
this.onRejectedArr = []; // 存储将要执行的reject函数
function resolveFn (val) { // resolve()时执行的函数
if (self.status === 'pending') { // 只用pending状态才能继续进行
self.value = val; // 存储数据
self.status = 'fulfilled'; // 改变状态
// 逐个调用then()函数
self.onFulfilledArr.forEach(function(thenFn) {
thenFn(self.value);
});
}
}
function rejectFn(errMsg) { // reject()时执行的函数
if (self.status === 'pending') {
self.err = errMsg;
self.status = 'rejected';
self.onRejectedArr.forEach(function(catchFn) {
catchFn(self.err);
});
}
}
try {
fn(resolveFn, rejectFn);
} catch (e) {
rejectFn(e);
}
}
实现then()函数
创建好了Promise构造函数下一步创建then()函数
MyPromise.prototype.then = function(onFulfilled, onRejected) {
// 如果当前处于pending状态,就将函数压入对应数组
var self = this;
if (self.status === 'pending') {
self.onFulfilledArr.push(onFulfilled);
self.onRejectedArr.push(onRejected);
}
// fulfilled状态就执行onFulfilled()方法
if (self.status === 'fulfilled') {
onFulfilled(self.value);
}
// onFulfilled状态就要执行onRejected()函数
if (self.status === 'rejected') {
onRejected(self.err);
}
return this; // return this是链式调用关键
};
到此我们就实现了自己的myPromise()方法。最关键的还是Promise的三种状态,理解了三种状态的切换就基本掌握了Promise。