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