Promise 原理探究及其簡單實現


可移步 http://donglegend.com/2016/09/11/promise%E5%8E%9F%E7%90%86%E6%8E%A2%E7%A9%B6/ 觀看

Promise是個什么玩意,大家都知道,度娘告訴我,以同步方式書寫異步,解決回調地獄。。。

狀態機

早聞Promise的大名,簡單介紹,根據狀態改變來執行相應處理函數。
Promise的狀態極其簡單,只有 “pending”, “resolved”, “rejected”三種狀態
然后就是如何實現的問題,最關鍵的當然是監聽到狀態的更新,然后才能做出回應,那么如何知道狀態變了呢?
最初單純的我開了一個腦洞,有以下想法:

  • 寫一個定時器不斷查詢狀態值,如果有變化,那么執行回調
  • 利用ES5的 Object.defineProperty(obj, prop, descriptor)來追蹤狀態變化。
  • 直接修改狀態為指定值,然后接着執行回調

嗚嗚嗚,有時候總會犯傻不是,上面第一種維護一個定時器,效率低下;第二種把狀態變得很麻煩和復雜;
其實很多事情之所以復雜,是因為我們想的太多。
Promise根本沒那么復雜,就三個狀態,搞毛線定時器,狀態跟蹤。
利用觀察者模式,只需要通過特定書寫方式注冊對應狀態的事件處理函數,然后更新狀態,調用注冊過的處理函數即可。這個特定方式就是 then ,done ,fail, always…等方法;更新狀態觸發時機就是resolve, reject方法。

簡單實現

理論分析:

  • 寫一個類對象,維護一個 state,值有3種:”pending”, “resolved”, “rejected”
  • 通過then done fail always方法注冊回調處理函數
  • 通過resolve reject分別更新對應狀態,並且調用注冊函數

代碼如下:

 1 /**
 2  * [3種狀態]
 3  * @type {String}
 4  */
 5 
 6 var PENDING = "pending";
 7 var RESOLVED = "resolved";
 8 var REJECTED = "rejected";
 9 /**
10  * [Promise類實現]
11  * 構造函數傳入一個fn,有兩個參數,resolve:成功回調; reject:失敗回調;
12  * state: 狀態存儲
13  * doneList: 成功處理函數列表
14  * failList: 失敗處理函數列表
15  * done: 注冊成功處理函數
16  * fail: 注冊失敗處理函數
17  * then: 同時注冊成功和失敗處理函數
18  * always: 一個處理注冊到成功和失敗,都會調用
19  * resolve: 更新state為:RESOLVED,並且執行成功處理隊列
20  * reject: 更新state為:REJECTED,並且執行失敗處理隊列
21  */
22 var Promise = (function (){
23     function Promise(fn){
24         this.state = PENDING;
25         this.doneList = [];
26         this.failList = [];
27         this.fn = fn;
28         this.fn(this.resolve.bind(this), this.reject.bind(this))
29     }
30 
31     var p = {
32         done: function (cb){
33             if(typeof cb == "function")
34                 this.doneList.push(cb)
35             return this;
36         },
37         fail: function(cb){
38             if(typeof cb == "function")
39                 this.failList.push(cb);
40             return this;
41         },
42         then: function(success, fail){
43             this.done(success || noop).fail(fail || noop)
44             return this;
45         },
46         always: function(cb){
47             this.done(cb).fail(cb)
48             return this;
49         },
50         resolve: function(){
51             this.state = RESOLVED;
52             var lists = this.doneList;
53             for(var i = 0, len = lists.length; i<len; i++){
54                 lists[0].apply(this, arguments);
55                 lists.shift();
56             }
57             return this;
58         },
59         reject: function(){
60             this.state = REJECTED;
61             var lists = this.failList;
62             for(var i = 0, len = lists.length; i<len; i++){
63                 lists[0].apply(this, arguments);
64                 lists.shift();
65             }
66             return this;
67         }
68     }
69     for(var k in p){
70         Promise.prototype[k] = p[k]
71     }
72 
73     return Promise;
74 })();
75 
76 function noop(){}

 使用方式,請到https://github.com/donglegend/MyPromise下載使用

 

源碼下載

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM