參考Promise 的 官方規範 https://promisesaplus.com/promise
Promise 其實就是一個狀態機異步
它只有兩種狀態變化 pending =》 fulfilled函數
pending =》 rejected測試
而且狀態一旦發生變化後就不會再改變this
咱們用es5來實現下es5
先寫個架子, 並測試下:spa
function myPromise(executor) { var _this = this; // 保存當前的函數上下文 _this.status = 'pending'; // 初始狀態 _this.resolveValue = null; // resolve初始值 _this.rejectValue = null; // reject初始值 function resolve(value) { if (_this.status == 'pending') { _this.status = 'Fulfilled'; _this.resolveValue = value; } } function reject(reason) { if (_this.status == 'pending') { _this.status = 'Fulfilled'; _this.rejectValue = reason; } } try { // 捕獲錯誤 executor(resolve, reject) } catch (e){ reject(e); } } myPromise.prototype.then = function (onFulfilled, onRejected) { var _this = this; if (_this.status == 'Fulfilled') { onFulfilled(_this.resolveValue) } if (_this.status == 'Rejected') { onRejected(_this.rejectValue) } }; var p = new myPromise((resolve, reject) => { resolve('I am handsome'); throw Error('捕獲錯誤') }); p.then((data) => { console.log(data) }, (err) => { console.log(err) } );
結果:prototype
它先執行resolve 狀態 變爲 Fulfilled ,3d
而後報錯 ,執行reject , 因爲此時狀態不是pending, 狀態仍是Fulfilledcode
Promise的核心是處理異步,
如今咱們的代碼並不能等待狀態的改變,
接下來咱們加上處理異步操做的功能, 並測試下
function myPromise(executor) { var _this = this; // 保存當前的函數上下文 _this.status = 'pending'; // 初始狀態 _this.resolveValue = null; // resolve初始值 _this.rejectValue = null; // reject初始值 _this.resolveCallbackList = []; // 存resolve的回調 _this.rejectCallbackList = []; // 存reject的回調 function resolve(value) { if (_this.status == 'pending') { _this.status = 'Fulfilled'; _this.resolveValue = value; // 狀態改變執行存的回調 _this.resolveCallbackList.forEach(function(ele){ if (ele) { ele(); } }) } } function reject(reason) { if (_this.status == 'pending') { _this.status = 'Rejected'; _this.rejectValue = reason; // 狀態改變執行存的回調 _this.rejectCallbackList.forEach(function(ele){ if (ele) { ele(); } }) } } try { // 捕獲錯誤 executor(resolve, reject) } catch (e){ reject(e); } } myPromise.prototype.then = function (onFulfilled, onRejected) { var _this = this; if (_this.status == 'Fulfilled') { onFulfilled(_this.resolveValue) } if (_this.status == 'Rejected') { onRejected(_this.rejectValue) } // 等待狀態時把回調存起來,狀態改變再觸發 if (_this.status == 'pending') { _this.resolveCallbackList.push(function () { onFulfilled(_this.resolveValue) }); _this.rejectCallbackList.push(function () { onRejected(_this.rejectValue) }); } }; var p = new myPromise((resolve, reject) => { setTimeout(() => { resolve('I am handsome'); }, 0); // throw Error('捕獲錯誤') }); p.then((data) => { console.log(data) }, (err) => { console.log(err) } );
結果:
🆗 它已經能處理異步操做了
接下來實現鏈式操做, 再測試下
function myPromise(executor) { var _this = this; // 保存當前的函數上下文 _this.status = 'pending'; // 初始狀態 _this.resolveValue = null; // resolve初始值 _this.rejectValue = null; // reject初始值 _this.resolveCallbackList = []; // 存resolve的回調 _this.rejectCallbackList = []; // 存reject的回調 function resolve(value) { if (_this.status == 'pending') { _this.status = 'Fulfilled'; _this.resolveValue = value; // 狀態改變執行存的回調 _this.resolveCallbackList.forEach(function(ele){ if (ele) { ele(); } }) } } function reject(reason) { if (_this.status == 'pending') { _this.status = 'Rejected'; _this.rejectValue = reason; // 狀態改變執行存的回調 _this.rejectCallbackList.forEach(function(ele){ if (ele) { ele(); } }) } } try { // 捕獲錯誤 executor(resolve, reject) } catch (e){ reject(e); } } myPromise.prototype.then = function (onFulfilled, onRejected) { var _this = this; // 用於鏈式調用 var nextPromise = new myPromise(function(res, rej) { if (_this.status == 'Fulfilled') { // 存一下回調執行的結果,傳給下一個.then var nextResolveValue = onFulfilled(_this.resolveValue); res(nextResolveValue); } if (_this.status == 'Rejected') { // 存一下回調執行的結果,傳給下一個.then var nextRejectValue = onRejected(_this.rejectValue); rej(nextRejectValue); } // 等待狀態時把回調存起來,狀態改變再觸發 if (_this.status == 'pending') { _this.resolveCallbackList.push(function () { // 存一下回調執行的結果,傳給下一個.then var nextResolveValue = onFulfilled(_this.resolveValue); res(nextResolveValue); }); _this.rejectCallbackList.push(function () { var nextRejectValue = onRejected(_this.rejectValue); rej(nextRejectValue); }); } }); return nextPromise }; var p = new myPromise((resolve, reject) => { setTimeout(() => { resolve('I am handsome'); }, 0); // throw Error('捕獲錯誤') }); p.then((data) => { console.log(data + ' suc' + ' 1') return 222 }, (err) => { console.log(err) } ).then((data) => { console.log(data + ' suc' + ' 2') }, (err) => { console.log(err) } );
結果 :
沒毛病, 能夠鏈式調用then了 , 先不處理返回值爲Promise 的 狀況 ,
原生的Promise 執行方法都是異步的 , 而且執行方法是能捕捉錯誤,
咱們加上這個功能 , 而且測試下
function myPromise(executor) { var _this = this; // 保存當前的函數上下文 _this.status = 'pending'; // 初始狀態 _this.resolveValue = null; // resolve初始值 _this.rejectValue = null; // reject初始值 _this.resolveCallbackList = []; // 存resolve的回調 _this.rejectCallbackList = []; // 存reject的回調 function resolve(value) { if (_this.status == 'pending') { _this.status = 'Fulfilled'; _this.resolveValue = value; // 狀態改變執行存的回調 _this.resolveCallbackList.forEach(function(ele){ if (ele) { ele(); } }) } } function reject(reason) { if (_this.status == 'pending') { _this.status = 'Rejected'; _this.rejectValue = reason; // 狀態改變執行存的回調 _this.rejectCallbackList.forEach(function(ele){ if (ele) { ele(); } }) } } try { // 捕獲錯誤 executor(resolve, reject) } catch (e){ reject(e); } } myPromise.prototype.then = function (onFulfilled, onRejected) { var _this = this; // 用於鏈式調用 var nextPromise = new myPromise(function(res, rej) { if (_this.status == 'Fulfilled') { // 存一下回調執行的結果,傳給下一個.then setTimeout(function () { // 捕獲錯誤 try { var nextResolveValue = onFulfilled(_this.resolveValue); res(nextResolveValue); } catch (e) { rej(e) } },0) } if (_this.status == 'Rejected') { // 存一下回調執行的結果,傳給下一個.then setTimeout(function () { // 捕獲錯誤 try { var nextRejectValue = onRejected(_this.rejectValue); rej(nextRejectValue); } catch (e) { rej(e) } },0) } // 等待狀態時把回調存起來,狀態改變再觸發 if (_this.status == 'pending') { _this.resolveCallbackList.push(function () { // 存一下回調執行的結果,傳給下一個.then setTimeout(function () { // 捕獲錯誤 try { var nextResolveValue = onFulfilled(_this.resolveValue); res(nextResolveValue); } catch (e) { rej(e) } },0) }); _this.rejectCallbackList.push(function () { setTimeout(function () { // 捕獲錯誤 try { var nextRejectValue = onRejected(_this.rejectValue); rej(nextRejectValue); } catch (e) { rej(e) } },0) }); } }); return nextPromise }; var p = new myPromise((resolve, reject) => { setTimeout(() => { resolve('I am handsome'); console.log(111) }, 0); // throw Error('捕獲錯誤') }); p.then((data) => { console.log(data + ' suc' + ' 1'); throw Error('bao cuo') }, (err) => { console.log(err + ' err' + ' 1') } ).then((data) => { console.log(data + ' suc' + ' 2') }, (err) => { console.log(err + ' err' + ' 2') } ); console.log(222);
預期結果 222 =》 111 =》 I am handsome suc 1 =》 Error: bao cuo err 2
實際結果:
沒毛病, 異步而且捕獲到錯誤了
咱們再來處理 空 then() 就是then裏面不傳參數的狀況, 並測試
myPromise.prototype.then = function (onFulfilled, onRejected) { // 參數爲空把值直接傳給下一個then if (!onFulfilled) { onFulfilled = function (val) { return val; } } if (!onRejected) { onRejected = function (val) { return new Error(val) } } var _this = this; // 用於鏈式調用 var nextPromise = new myPromise(function(res, rej) { if (_this.status == 'Fulfilled') { // 存一下回調執行的結果,傳給下一個.then setTimeout(function () { // 捕獲錯誤 try { var nextResolveValue = onFulfilled(_this.resolveValue); res(nextResolveValue); } catch (e) { rej(e) } },0) } if (_this.status == 'Rejected') { // 存一下回調執行的結果,傳給下一個.then setTimeout(function () { // 捕獲錯誤 try { var nextRejectValue = onRejected(_this.rejectValue); rej(nextRejectValue); } catch (e) { rej(e) } },0) } // 等待狀態時把回調存起來,狀態改變再觸發 if (_this.status == 'pending') { _this.resolveCallbackList.push(function () { // 存一下回調執行的結果,傳給下一個.then setTimeout(function () { // 捕獲錯誤 try { var nextResolveValue = onFulfilled(_this.resolveValue); res(nextResolveValue); } catch (e) { rej(e) } },0) }); _this.rejectCallbackList.push(function () { setTimeout(function () { // 捕獲錯誤 try { var nextRejectValue = onRejected(_this.rejectValue); rej(nextRejectValue); } catch (e) { rej(e) } },0) }); } }); return nextPromise }; var p = new myPromise((resolve, reject) => { setTimeout(() => { resolve('I am handsome'); }, 0); // throw Error('捕獲錯誤') }); p.then((data) => { console.log(data + ' suc' + ' 1'); throw Error('bao cuo') }, (err) => { console.log(err + ' err' + ' 1') } ).then( ).then((data) => { console.log(data + ' suc' + ' 3') }, (err) => { console.log(err + ' err' + ' 3') } );
結果:
🆗 第一個then裏拋出的錯誤被第三個then 接受到了, 沒毛病
接下來處理 返回值爲promise的狀況, 並測試
若是返回值爲promise,後面的then就取決於返回的promise的狀態
// 處理返回值的函數 function ResolutionRetrunPromise (nextPromise, returnValue, res, rej) { // 返回值是不是promise if (returnValue instanceof myPromise) { returnValue.then(function (val) { res(val) },function (reason) { rej(reason) }) } else { res(returnValue) } } myPromise.prototype.then = function (onFulfilled, onRejected) { // 參數爲空把值直接傳給下一個then if (!onFulfilled) { onFulfilled = function (val) { return val; } } if (!onRejected) { onRejected = function (reason) { return new Error(reason) } } var _this = this; // 用於鏈式調用 var nextPromise = new myPromise(function(res, rej) { if (_this.status == 'Fulfilled') { // 存一下回調執行的結果,傳給下一個.then setTimeout(function () { // 捕獲錯誤 try { var nextResolveValue = onFulfilled(_this.resolveValue); // 處理返回值 ResolutionRetrunPromise(nextPromise, nextResolveValue, res, rej) // res(nextResolveValue); } catch (e) { rej(e) } },0) } if (_this.status == 'Rejected') { // 存一下回調執行的結果,傳給下一個.then setTimeout(function () { // 捕獲錯誤 try { var nextRejectValue = onRejected(_this.rejectValue); ResolutionRetrunPromise(nextPromise, nextRejectValue, res, rej) // rej(nextRejectValue); } catch (e) { rej(e) } },0) } // 等待狀態時把回調存起來,狀態改變再觸發 if (_this.status == 'pending') { _this.resolveCallbackList.push(function () { // 存一下回調執行的結果,傳給下一個.then setTimeout(function () { // 捕獲錯誤 try { var nextResolveValue = onFulfilled(_this.resolveValue); ResolutionRetrunPromise(nextPromise, nextResolveValue, res, rej) // res(nextResolveValue); } catch (e) { rej(e) } },0) }); _this.rejectCallbackList.push(function () { setTimeout(function () { // 捕獲錯誤 try { var nextRejectValue = onRejected(_this.rejectValue); ResolutionRetrunPromise(nextPromise, nextRejectValue, res, rej) // rej(nextRejectValue); } catch (e) { rej(e) } },0) }); } }); return nextPromise }; var p = new myPromise((resolve, reject) => { setTimeout(() => { resolve('I am handsome'); }, 1000); }); p.then((data) => { console.log(data + ' suc' + ' 1'); return new myPromise((resolve, reject) => { reject('promise') }) }, (err) => { console.log(err + ' err' + ' 1') } ).then((data) => { console.log(data + ' suc' + ' 3') }, (err) => { console.log(err + ' err' + ' 3') } );
結果:
到此 Promise 的 基本功能就實現了 ,
感興趣的同窗能夠基於此 本身實現一下Promise 的 靜態方法 。 。 。 。。 。