Promise是前端面试中的高频问题,我做为面试官的时候,问Promise的几率超过90%,据我所知,大多数公司,都会问一些关于Promise的问题。若是你能根据PromiseA+的规范,写出符合规范的源码,那么我想,对于面试中的Promise相关的问题,都可以给出比较完美的答案。前端
个人建议是,对照规范多写几回实现,也许第一遍的时候,是改了屡次,才能经过测试,那么须要反复的写,我已经将Promise的源码实现写了不下七遍。面试
/**
* 1. new Promise时,须要传递一个 executor 执行器,执行器马上执行 * 2. executor 接受两个参数,分别是 resolve 和 reject * 3. promise 只能从 pending 到 rejected, 或者从 pending 到 fulfilled * 4. promise 的状态一旦确认,就不会再改变 * 5. promise 都有 then 方法,then 接收两个参数,分别是 promise 成功的回调 onFulfilled, * 和 promise 失败的回调 onRejected * 6. 若是调用 then 时,promise已经成功,则执行 onFulfilled,并将promise的值做为参数传递进去。 * 若是promise已经失败,那么执行 onRejected, 并将 promise 失败的缘由做为参数传递进去。 * 若是promise的状态是pending,须要将onFulfilled和onRejected函数存放起来,等待状态肯定后,再依次将对应的函数执行(发布订阅) * 7. then 的参数 onFulfilled 和 onRejected 能够缺省 * 8. promise 能够then屡次,promise 的then 方法返回一个 promise * 9. 若是 then 返回的是一个结果,那么就会把这个结果做为参数,传递给下一个then的成功的回调(onFulfilled) * 10. 若是 then 中抛出了异常,那么就会把这个异常做为参数,传递给下一个then的失败的回调(onRejected) * 11.若是 then 返回的是一个promise,那么须要等这个promise,那么会等这个promise执行完,promise若是成功, * 就走下一个then的成功,若是失败,就走下一个then的失败 */ const PENDING = 'pending'; const FULFILLED = 'fulfilled'; const REJECTED = 'rejected'; function Promise(executor) { let self = this; self.status = PENDING; self.onFulfilled = [];//成功的回调 self.onRejected = []; //失败的回调 //PromiseA+ 2.1 function resolve(value) { if (self.status === PENDING) { self.status = FULFILLED; self.value = value; self.onFulfilled.forEach(fn => fn());//PromiseA+ 2.2.6.1 } } function reject(reason) { if (self.status === PENDING) { self.status = REJECTED; self.reason = reason; self.onRejected.forEach(fn => fn());//PromiseA+ 2.2.6.2 } } try { executor(resolve, reject); } catch (e) { reject(e); } } Promise.prototype.then = function (onFulfilled, onRejected) { //PromiseA+ 2.2.1 / PromiseA+ 2.2.5 / PromiseA+ 2.2.7.3 / PromiseA+ 2.2.7.4 onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value; onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }; let self = this; //PromiseA+ 2.2.7 let promise2 = new Promise((resolve, reject) => { if (self.status === FULFILLED) { //PromiseA+ 2.2.2 //PromiseA+ 2.2.4 --- setTimeout setTimeout(() => { try { //PromiseA+ 2.2.7.1 let x = onFulfilled(self.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { //PromiseA+ 2.2.7.2 reject(e); } }); } else if (self.status === REJECTED) { //PromiseA+ 2.2.3 setTimeout(() => { try { let x = onRejected(self.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); } else if (self.status === PENDING) { self.onFulfilled.push(() => { setTimeout(() => { try { let x = onFulfilled(self.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); }); self.onRejected.push(() => { setTimeout(() => { try { let x = onRejected(self.reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); }); } }); return promise2; } function resolvePromise(promise2, x, resolve, reject) { let self = this; //PromiseA+ 2.3.1 if (promise2 === x) { reject(new TypeError('Chaining cycle