Promise對你們來講並非很陌生,它是一個異步編程的解決方案,主要解決了前端回調地域問題。用阮老師的話說,它「就是一個容器,裏面保存着某個將來纔會結束的事件(一般是一個異步操做)的結果」。前端
Promise有三種狀態:pending(初始狀態)、fulfilled(成功)、reject(失敗),初始狀態pending只能變成fulfilled或者reject,這一過程是不可逆的,當狀態發生改變時,會觸發對應的回調方法。除此以外,也支持鏈式調用,then/catch會返回一個Promise,以供鏈式調用,盜用MDN上的一張圖,Promise的執行流程以下圖所示:編程
具體實現簡單分爲如下四步:promise
一、定義一個執行器fn,自帶兩個參數的函數,resolve/reject,在實例化Promise時,調用執行器fn,傳入參數reslove/reject,初始化回調事件隊列taskList
二、在執行then方法時,判斷是否是初始狀態pending,若是是,則將then中fullfilled/reject的回調推動執行隊列taskList中,then方法返回一個promise實例
三、實現鏈式回調中,用id來標識不一樣的promise實例
四、當觸發了執行器中參數函數時,根據id來判斷當前執行的回調方法異步
實現代碼:異步編程
1 //公共變量,用於標識MyPromise實例 2 index = 0; 3 //promise接收一個回調函數fn,有兩個參數,reslove,reject 4 function MyPromise(fn) { 5 var _this = this; 6 //promise的三種狀態 7 this.RESOLVE = "fullfilled"; 8 this.PENDING = "pending"; 9 this.REJECT = "reject"; 10 this.id = index++; 11 //初始默認狀態爲penddding 12 this.state = this.PENDING; 13 //執行任務列表 14 this.taskList = []; 15 //最終執行的回調 16 this.finallyCallback = null; 17 //bind改變reslove/reject函數體內this的指向,確保指向MyPromise 18 fn.call(this, this.resolve.bind(this), this.reject.bind(this)); 19 } 20 21 MyPromise.prototype.resolve = function(value) { 22 this.state = this.RESOLVE; 23 //二、狀態變動時,執行完成的方法 24 this.taskList[this.id] && this.handler(this.taskList[this.id], value); 25 }; 26 27 MyPromise.prototype.reject = function(value) { 28 this.state = this.REJECT; 29 //二、狀態變動時,執行完成的方法 30 this.taskList[this.id] && this.handler(this.taskList[this.id], value); 31 }; 32 //執行任務回調 33 MyPromise.prototype.handler = function(task, value) { 34 var result = null; 35 if (this.state === this.RESOLVE) { 36 result = task.onFullFilled(value); 37 } else if (this.state === this.REJECT) { 38 result = task.onReject(value); 39 } 40 var nextId = this.id + 1; 41 //須要判斷返回值是否是MyPromise實例,若是是,將以前的任務隊列賦值給新的MyPromise實例 42 if (result instanceof MyPromise) { 43 result.id = nextId; 44 result.taskList = this.taskList; 45 result.finallyCallback = this.finallyCallback; 46 } else { 47 //沒有返回MyPromise實例 48 //若是有finally回調,則執行最終的回調 49 this.finallyCallback && this.finallyCallback(); 50 } 51 }; 52 //onFullFilled:成功的回調,onReject:失敗的回調 53 MyPromise.prototype.then = function(onFullFilled, onReject) { 54 var _this = this, 55 obj = { 56 onFullFilled: onFullFilled, 57 onReject: onReject 58 }; 59 //一、初始化時,將後續可能要執行的任務推送到執行任務隊列中 60 if (this.state === this.PENDING) { 61 this.taskList.push(obj); 62 } 63 //返回一個promise,支持鏈式調用 64 return this; 65 }; 66 67 //最終執行的方法,無論MyPromise的狀態如何 68 MyPromise.prototype.finally = function(callback) { 69 this.finallyCallback = callback; 70 };
測試代碼:函數
var cc = new MyPromise(function(reslove, reject) { setTimeout(function() { reslove(2); }, 500); }); var dd = new MyPromise(function(reslove, reject) { setTimeout(function() { reject(3); }, 500); }); cc.then(function(num) { console.log(num); return dd; }) .then( function(cc) { console.log(cc); }, function(e) { console.log(5); } ) .finally(function() { console.log("Game Over"); }); console.log(1);
執行結果:測試
實現過程簡單粗暴,若有問題,煩請指出,謝謝!this