在手写Promise之前,需要先了解Promise。
语法:const p = new Promise((resolve,reject)=>{...} )
在创建对象时,传入一个函数参数,同时函数立即执行,函数又接受两个函数作为参数,调用resolve或者reject后状态发生改变且不会再变。
promise有三个状态,分别是pending,fulfilled,rejected,在创建对象之初为pending(待定)状态,调用resolve后变为fullfilled(成功)状态,调用reject后变为rejected(失败)状态。
状态改变后,会调用then方法里的回调。then方法一般接受两个回调函数作为参数,第一个onFulfilled,状态变为fulfilled会执行。第二个onRejected,状态变为rejected会执行。均返回一个新的promise对象,返回的promise对象状态与传的参数有关,这里不再细分,以后再说。
catch方法等同于then方法里rejected的回调,如果任务处于rejected状态则就不在执行then回调,而是去执行catch的回调。
then或catch方法里的回调,会将任务放到微队列去执行。
好,明白了promise的大体步骤,再来看怎么去手写一个promise。
这是一个符合Promise/A+的代码,具体我也说不上来,只能多看几遍,明白了其原理还是挺简单的。
// 定义三种状态
const PENDING = 'pending'; // 初始状态,等待
const FULFILLED = 'fulfilled'; // 成功状态
const REJECTED = 'rejected'; // 失败状态
// Promise构造函数
function Promise(executor) {
var _this = this; // 当前的promise实例
this.state = PENDING; // 初始化状态为等待
this.value = undefined; // 成功时的值
this.reason = undefined; // 失败时的理由
this.onFulfilled = []; // 成功的回调函数列表
this.onRejected = []; // 失败的回调函数列表
// 成功解决时的处理函数
function resolve(value) {
if (_this.state === PENDING) {
_this.state = FULFILLED; // 状态改为成功
_this.value = value; // 成功时的值设为传入的value
_this.onFulfilled.forEach(fn => fn(value)); // 执行所有的成功回调
}
}
// 拒绝promise时的处理函数
function reject(reason) {
if (_this.state === PENDING) {
_this.state = REJECTED; // 状态改为失败
_this.reason = reason; // 失败时的理由设为传入的原因
_this.onRejected.forEach(fn => fn(reason)); // 执行所有的失败回调
}
}
// 尝试执行executor,并捕获可能出现的异常
try {
executor(resolve, reject);
} catch (e) {
reject(e); // 如果executor中有异常,直接拒绝promise
}
}
// 提供一个deferred API,等价于Promise.defer或Promise.deferred
Promise.defer = Promise.deferred = function () {
let dfd = {}; // 创建一个对象来保存结果和回调
dfd.promise = new Promise((resolve, reject) => {
dfd.resolve = resolve; // 保存解决函数
dfd.reject = reject; // 保存拒绝函数
});
return dfd; // 返回这个deferred对象
}
// 原型上的then方法,允许添加成功和失败的回调
Promise.prototype.then = function (onFulfilled, onRejected) {
// onFulfilled和onRejected如果不是函数,则默认分别返回value和抛出reason
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
// 创建一个新的promise
var promise2 = new Promise((resolve, reject) => {
if (_this.state === FULFILLED) {
// 如果当前状态是成功,则异步执行onFulfilled,并将结果 resolve(promise2)
setTimeout(() => {
try {
let x = onFulfilled(_this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
} else if (_this.state === REJECTED) {
// 如果当前状态是失败,则异步执行onRejected,并将结果 resolve(promise2)
setTimeout(() => {
try {
let x = onRejected(_this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
} else if (_this.state === PENDING) {
// 如果当前状态是等待,则将onFulfilled和onRejected函数存起来
_this.onFulfilled.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(_this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
_this.onRejected.push(() => {
setTimeout(() => {
try {
let x = onRejected(_this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
}
});
// 返回新的promise
return promise2;
};
// resolvePromise的辅助函数,用于正确处理promise的链式调用
function resolvePromise(promise2, x, resolve, reject) {
// 如果promise2和x相同,则拒绝promise,防止循环引用
if (promise2 === x) {
reject(new TypeError('Chaining cycle'));
}
// 如果x是一个对象或者函数
if (x && (typeof x === 'object' || typeof x === 'function')) {
// 尝试获取x的then方法
let used;
try {
let then = x.then;
if (typeof then === 'function') {
// 如果是thenable,则使用它的then方法,并处理返回的结果
then.call(
x,
y => {
if (used) return;
used = true;
resolvePromise(promise2, y, resolve, reject);
},
r => {
if (used) return;
used = true;
reject(r);
}
);
} else {
// 如果x是一个普通对象,直接resolve
resolve(x);
}
} catch (e) {
if (used) return;
used = true;
reject(e);
}
} else {
// 如果x不是对象或函数,直接resolve
resolve(x);
}
}