大体思路:
resolve方法实现异步的回调并得到结果通知,然后再通知onFulfilled
reject方法实现异步的回调并得到错误反馈,然后再通知onRejected
then方法实现对onFulfilled和onRejected的二次封装后,加载到回调队列_resolveQueue/_rejectQueue,等候通知,并且返回新的pomise实现链式调用
版本一
这个版本有个问题:当传给reject回调的参数是 promise 对象时,没做处理。
// Promise/A+ 规范规定的三种状态const STATUS = {PENDING: 'pending',FULFILLED: 'fulfilled',REJECTED: 'rejected'}class MyPromise {// 构造函数接收一个执行回调constructor(executor) {this._status = STATUS.PENDING // Promise初始状态this._value = undefined // then回调的值this._resolveQueue = [] // resolve时触发的成功队列this._rejectQueue = [] // reject时触发的失败队列// 使用箭头函数固定this(resolve函数在executor中触发,不然找不到this)const resolve = value => {const run = () => {// Promise/A+ 规范规定的Promise状态只能从pending触发,变成fulfilledif (this._status === STATUS.PENDING) {this._status = STATUS.FULFILLED // 更改状态this._value = value // 储存当前值,用于then回调// 执行resolve回调while (this._resolveQueue.length) {const callback = this._resolveQueue.shift()callback(value)}}}//把resolve执行回调的操作封装成一个函数,放进setTimeout里,以实现promise异步调用的特性(规范上是微任务,这里是宏任务)setTimeout(run)}// 同 resolveconst reject = value => {const run = () => {if (this._status === STATUS.PENDING) {this._status = STATUS.REJECTEDthis._value = valuewhile (this._rejectQueue.length) {const callback = this._rejectQueue.shift()callback(value)}}}setTimeout(run)}// new Promise()时立即执行executor,并传入resolve和rejectexecutor(resolve, reject)}// then方法,接收一个成功的回调和一个失败的回调then(onFulfilled, onRejected) {// 根据规范,如果then的参数不是function,则忽略它, 让值继续往下传递,链式调用继续往下执行typeof onFulfilled !== 'function' ? onFulfilled = value => value : nulltypeof onRejected !== 'function' ? onRejected = error => error : null// then 返回一个新的promisereturn new MyPromise((resolve, reject) => {const resolveFn = value => {try {const x = onFulfilled(value)// 分类讨论返回值,如果是Promise,那么等待Promise状态变更,否则直接resolvex instanceof MyPromise ? x.then(resolve, reject) : resolve(x)} catch (error) {reject(error)}}const rejectFn = error => {try {const x = onRejected(error)x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)} catch (error) {reject(error)}}switch (this._status) {case STATUS.PENDING:this._resolveQueue.push(resolveFn)this._rejectQueue.push(rejectFn)break;case STATUS.FULFILLED:resolveFn(this._value)break;case STATUS.REJECTED:rejectFn(this._value)break;}})}catch(rejectFn) {return this.then(undefined, rejectFn)}finally(callback) {return this.then(value => MyPromise.resolve(callback()).then(() => value), error => {MyPromise.resolve(callback()).then(() => error)})}// 静态resolve方法static resolve(value) {return value instanceof MyPromise ? value : new MyPromise(resolve => resolve(value))}// 静态reject方法static reject(error) {return new MyPromise((resolve, reject) => reject(error))}// 静态all方法static all(promiseArr) {let count = 0let result = []return new MyPromise((resolve, reject) => {if (!promiseArr.length) {return resolve(result)}promiseArr.forEach((p, i) => {MyPromise.resolve(p).then(value => {count++result[i] = valueif (count === promiseArr.length) {resolve(result)}}, error => {reject(error)})})})}// 静态race方法static race(promiseArr) {return new MyPromise((resolve, reject) => {promiseArr.forEach(p => {MyPromise.resolve(p).then(value => {resolve(value)}, error => {reject(error)})})})}}
版本二
// 判断变量否为functionconst isFunction = variable => typeof variable === 'function'// 定义Promise的三种状态常量const PENDING = 'PENDING'const FULFILLED = 'FULFILLED'const REJECTED = 'REJECTED'class MyPromise {constructor (handle) {if (!isFunction(handle)) {throw new Error('MyPromise must accept a function as a parameter')}// 添加状态this._status = PENDING// 添加状态this._value = undefined// 添加成功回调函数队列this._fulfilledQueues = []// 添加失败回调函数队列this._rejectedQueues = []// 执行handletry {handle(this._resolve.bind(this), this._reject.bind(this))} catch (err) {this._reject(err)}}// 添加resovle时执行的函数_resolve (val) {const run = () => {if (this._status !== PENDING) return// 依次执行成功队列中的函数,并清空队列const runFulfilled = (value) => {let cb;while (cb = this._fulfilledQueues.shift()) {cb(value)}}// 依次执行失败队列中的函数,并清空队列const runRejected = (error) => {let cb;while (cb = this._rejectedQueues.shift()) {cb(error)}}/* 如果resolve的参数为Promise对象,则必须等待该Promise对象状态改变后,当前Promsie的状态才会改变,且状态取决于参数Promsie对象的状态*/if (val instanceof MyPromise) {val.then(value => {this._value = valuethis._status = FULFILLEDrunFulfilled(value)}, err => {this._value = errthis._status = REJECTEDrunRejected(err)})} else {this._value = valthis._status = FULFILLEDrunFulfilled(val)}}// 为了支持同步的Promise,这里采用异步调用setTimeout(run, 0)}// 添加reject时执行的函数_reject (err) {if (this._status !== PENDING) return// 依次执行失败队列中的函数,并清空队列const run = () => {this._status = REJECTEDthis._value = errlet cb;while (cb = this._rejectedQueues.shift()) {cb(err)}}// 为了支持同步的Promise,这里采用异步调用setTimeout(run, 0)}// 添加then方法then (onFulfilled, onRejected) {const { _value, _status } = this// 返回一个新的Promise对象return new MyPromise((onFulfilledNext, onRejectedNext) => {// 封装一个成功时执行的函数let fulfilled = value => {try {if (!isFunction(onFulfilled)) {onFulfilledNext(value)} else {let res = onFulfilled(value);if (res instanceof MyPromise) {// 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调res.then(onFulfilledNext, onRejectedNext)} else {//否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数onFulfilledNext(res)}}} catch (err) {// 如果函数执行出错,新的Promise对象的状态为失败onRejectedNext(err)}}// 封装一个失败时执行的函数let rejected = error => {try {if (!isFunction(onRejected)) {onRejectedNext(error)} else {let res = onRejected(error);if (res instanceof MyPromise) {// 如果当前回调函数返回MyPromise对象,必须等待其状态改变后在执行下一个回调res.then(onFulfilledNext, onRejectedNext)} else {//否则会将返回结果直接作为参数,传入下一个then的回调函数,并立即执行下一个then的回调函数onFulfilledNext(res)}}} catch (err) {// 如果函数执行出错,新的Promise对象的状态为失败onRejectedNext(err)}}switch (_status) {// 当状态为pending时,将then方法回调函数加入执行队列等待执行case PENDING:this._fulfilledQueues.push(fulfilled)this._rejectedQueues.push(rejected)break// 当状态已经改变时,立即执行对应的回调函数case FULFILLED:fulfilled(_value)breakcase REJECTED:rejected(_value)break}})}// 添加catch方法catch (onRejected) {return this.then(undefined, onRejected)}// 添加静态resolve方法static resolve (value) {// 如果参数是MyPromise实例,直接返回这个实例if (value instanceof MyPromise) return valuereturn new MyPromise(resolve => resolve(value))}// 添加静态reject方法static reject (value) {return new MyPromise((resolve ,reject) => reject(value))}// 添加静态all方法static all (list) {return new MyPromise((resolve, reject) => {/*** 返回值的集合*/let values = []let count = 0for (let [i, p] of list.entries()) {// 数组参数如果不是MyPromise实例,先调用MyPromise.resolvethis.resolve(p).then(res => {values[i] = rescount++// 所有状态都变成fulfilled时返回的MyPromise状态就变成fulfilledif (count === list.length) resolve(values)}, err => {// 有一个被rejected时返回的MyPromise状态就变成rejectedreject(err)})}})}// 添加静态race方法static race (list) {return new MyPromise((resolve, reject) => {for (let p of list) {// 只要有一个实例率先改变状态,新的MyPromise的状态就跟着改变this.resolve(p).then(res => {resolve(res)}, err => {reject(err)})}})}finally (cb) {return this.then(value => MyPromise.resolve(cb()).then(() => value),reason => MyPromise.resolve(cb()).then(() => { throw reason }));}}
版本三
const isFunc = obj => Object.prototype.toString.call(obj) === '[object Function]';
const isObj = obj => Object.prototype.toString.call(obj) === '[object Object]';
// 等待态 规范 2.1.1
const PENDING = 'pending';
// 执行态 规范 2.1.2
const FULFILLED = 'fulfilled';
// 拒绝态 规范 2.1.3
const REJECTED = 'rejected';
class MyPromise {
constructor(fn) {
this.status = PENDING;
this.value = undefined;
this.filfulledQueues = [];
this.rejectedQueues = [];
try {
fn(this._resolve.bind(this), this._reject.bind(this));
} catch (err) {
this._reject(err);
}
}
//传入 promise 的第一个参数 resolve
_resolve(val) {
if (val instanceof MyPromise) {
val.then(this._resolve, this._reject);
} else if (isObj(val) || isFunc(val)) {
try {
if (isFunc(val.then)) {
val.then(this._resolve, this._reject);
}
} catch (e) {
this._reject(e);
}
}
this._execCallback(FULFILLED, this.filfulledQueues, val);
}
//传入 promise 的第二个参数 reject
_reject(val) {
this._execCallback(REJECTED, this.rejectedQueues, val);
}
_execCallback(status, list, val) {
//规范 2.2.4 onFulfilled 和 onRejected 只有在执行环境堆栈仅包含平台代码时才可被调用,且被作为函数调用(即没有 this 值)
setTimeout(() => {
if (this.status !== PENDING) {
return;
}
this.status = status;
this.value = val;
let cb;
//规范 2.2.6
while ((cb = list.shift())) {
cb(val);
}
});
}
//规范 2.3 Promise 解决过程 [[Resolve]](promise, x)
_resolvePromise(newPromise, x, resolve, reject) {
if (newPromise === x) {
//规范 2.3.1
return reject(new TypeError('循环引用'));
}
if (x instanceof MyPromise) {
//规范 2.3.2
x.then(resolve, reject);
} else if (isObj(x) || isFunc(x)) {
//规范 2.3.3
try {
//规范 2.3.3.3
if (isFunc(x.then)) {
x.then(resolve, reject);
} else {
//规范 2.3.3.4
resolve(x);
}
} catch (e) {
//规范 2.3.3.3.4
reject(e);
}
} else {
//规范 2.3.4
resolve(x);
}
}
//规范 2.2
then(onFulfilled, onRejected) {
let newPromise;
//规范 2.2.1,2.2.7.3
onFulfilled = isFunc(onFulfilled) ? onFulfilled : val => val;
//规范 2.2.1,2.2.7.4
onRejected = isFunc(onRejected)
? onRejected
: err => {
throw err;
};
//规范 2.2.7 then 方法必须返回一个 promise 对象:promise2 = promise1.then(onFulfilled, onRejected);
return (newPromise = new MyPromise((onFulfilledNext, onRejectedNext) => {
// onFulfilledNext, onRejectedNext 即该 then 的下一个 then 里传的 resolve 和 reject
if (this.status === FULFILLED || this.status === REJECTED) {
//规范 2.2.4 onFulfilled 和 onRejected 只有在执行环境堆栈仅包含平台代码时才可被调用
setTimeout(() => {
// 规范 2.2.7.1 不论 promise1 被 reject 还是被 resolve 时 promise2 都会被 resolve(走_resolvePromise方法),只有出现异常时才会被 rejected。
try {
//规范 2.2.2,2.2.3,2.2.5
const x = this.status === FULFILLED ? onFulfilled(this.value) : onRejected(this.value);
this._resolvePromise(newPromise, x, onFulfilledNext, onRejectedNext);
} catch (e) {
//规范 2.2.7.2 这里如果x为捕获的err(即 onRejected 不是函数 2.2.7.4)也会进入
onRejectedNext(e);
}
});
} else if (this.status === PENDING) {
//规范 2.2.6.1
this.filfulledQueues.push(() => {
try {
//规范 2.2.2,2.2.5
const x = onFulfilled(this.value);
this._resolvePromise(newPromise, x, onFulfilledNext, onRejectedNext);
} catch (e) {
//规范 2.2.7.2
onRejectedNext(e);
}
});
//规范 2.2.6.2
this.rejectedQueues.push(() => {
try {
//规范 2.2.3,2.2.5
const x = onRejected(this.value);
this._resolvePromise(newPromise, x, onFulfilledNext, onRejectedNext);
} catch (e) {
//规范 2.2.7.2
onRejectedNext(e);
}
});
}
}));
}
//catch 方法
catch(onRejected) {
return this.then(null, onRejected);
}
//finally 方法
finally(cb) {
return this.then(
val => {
MyPromise.resolve(cb()).then(() => val);
},
err => {
MyPromise.resolve(cb()).then(() => {
throw err;
});
}
);
}
//resolve 方法
static resolve(params) {
return new MyPromise(resolve => {
resolve(params);
});
}
//reject 方法
static reject(err) {
return new MyPromise((resolve, reject) => {
reject(err);
});
}
//all 方法
static all(params) {
let count = 0;
let valueList = [];
const promises = Array.from(params);
return new MyPromise((resolve, reject) => {
promises.forEach((item, index) => {
if (!item instanceof MyPromise) {
item = MyPromise.resolve(item);
}
item.then(r => {
valueList[index] = r;
if (promises.length === ++count) {
resolve(valueList);
}
}, reject);
});
});
}
//race 方法
static race(params) {
const promises = Array.from(params);
return new MyPromise((resolve, reject) => {
promises.forEach(item => {
if (!item instanceof MyPromise) {
item = MyPromise.resolve(item);
}
item.then(resolve, reject);
});
});
}
}
参考
Promise系列2——Promises_A+ 规范解读
https://promisesaplus.com/
看了就会,手写Promise原理,最通俗易懂的版本!!!
promise规范实现
Promise知识汇总和面试情况
