全面理解Javascript中Promise

來源:互聯網
上載者:User

標籤:blank   標準   分析   href   沒有   同步   net   進階之路   span   

全面理解Javascript中Promise

最近在學習Promise的時候,在網上收集了一些資料,發現很多的知識點不夠系統,所以小編特意為大家整理了一些自認為 
比較好的文章,供大家更好地學習js中非常有趣的Promise

Promise概念

2015 年 6 月,ECMAScript 6 的正式版 終於發布了。

ECMAScript 是 JavaScript 語言的國際標準,javascript 是 ECMAScript 的實現。ES6 的目標,是使得 JavaScript 語言可以用來編寫大型的複雜的應用程式,成為企業級開發語言。

–Promise知識JS的一個新對象,為的就是解決js在處理非同步時候產生的多成回調的問題,那麼在Promise納入ES6的規範之前,一些優秀 
的架構是如何解決這種非同步回調的問題的呢? 
在jQuery這個傳奇的架構中,已經有方法解決上述問題的方案了,那就是jquery的deferred對象,還沒有接觸到這個對象的小同學可以想去 
瞭解一下,推薦一篇博文jQuery的deferred對象詳解。當我瞭解到JQ中 
deferred對象的時候,就發現Promise的奧秘其實很簡單,跟deferred對象的實現方法有著異曲同工之妙。下面開始從Promise的基礎,Promise應用出髮帶大家瞭解Promise的美妙

Promise基礎

–ES6 原生提供了 Promise 對象。

所謂 Promise,就是一個對象,用來傳遞非同步作業的訊息。它代表了某個未來才會知道結果的事件(通常是一個非同步作業),並且這個事件提供統一的 API,可供進一步處理。

Promise 對象有以下兩個特點。

(1)對象的狀態不受外界影響。Promise 對象代表一個非同步作業,有三種狀態:Pending(進行中)、Resolved(已完成,又稱 Fulfilled)和 Rejected(已失敗)。只有非同步作業的結果,可以決定當前是哪一種狀態,任何其他動作都無法改變這個狀態。這也是 Promise 這個名字的由來,它的英語意思就是「承諾」,表示其他手段無法改變。

(2)一旦狀態改變,就不會再變,任何時候都可以得到這個結果。Promise 對象的狀態改變,只有兩種可能:從 Pending 變為 Resolved 和從 Pending 變為 Rejected。只要這兩種情況發生,狀態就凝固了,不會再變了,會一直保持這個結果。就算改變已經發生了,你再對 Promise 對象添加回呼函數,也會立即得到這個結果。這與事件(Event)完全不同,事件的特點是,如果你錯過了它,再去監聽,是得不到結果的。

有了 Promise 對象,就可以將非同步作業以同步操作的流程表達出來,避免了層層嵌套的回呼函數。此外,Promise 對象提供統一的介面,使得控制非同步作業更加容易。

Promise 也有一些缺點。首先,無法取消 Promise,一旦建立它就會立即執行,無法中途取消。其次,如果不設定回呼函數,Promise 內部拋出的錯誤,不會反應到外部。第三,當處於 Pending 狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)。

var promise = new Promise(function(resolve, reject) { if (/* 非同步作業成功 */){ resolve(value); } else { reject(error); }});promise.then(function(value) { // success}, function(value) { // failure});

 

Promise 建構函式接受一個函數作為參數,該函數的兩個參數分別是 resolve 方法和 reject 方法。

如果非同步作業成功,則用 resolve 方法將 Promise 對象的狀態,從「未完成」變為「成功」(即從 pending 變為 resolved);

如果非同步作業失敗,則用 reject 方法將 Promise 對象的狀態,從「未完成」變為「失敗」(即從 pending 變為 rejected)。

使用Promise組織你的AJAX
//建立一個Promise執行個體,擷取資料。並把資料傳遞給處理函數resolve和reject。需要注意的是Promise在聲明的時候就執行了。var getUserInfo=new Promise(function(resolve,reject){    $.ajax({        type:"get",        url:"index.aspx",        success:function(data){            if(data.Status=="1"){                resolve(data.ResultJson)//在非同步作業成功時調用            }else{                reject(data.ErrMsg);//在非同步作業失敗時調用            }        }    });})//另一個ajax Promise對象,var getDataList=new Promise(function(resolve,reject){    $.ajax({        type:"get",        url:"index.aspx",        success:function(data){            if(data.Status=="1"){                resolve(data.ResultJson)//在非同步作業成功時調用            }else{                reject(data.ErrMsg);//在非同步作業失敗時調用            }        }    });})//Promise的方法then,catch方法getUserInfo.then(function(ResultJson){    //通過拿到的資料渲染頁面}).catch(function(ErrMsg){    //擷取資料失敗時的處理邏輯})//Promise的all方法,等數組中的所有promise對象都完成執行Promise.all([getUserInfo,getDataList]).then(function([ResultJson1,ResultJson2]){    //這裡寫等這兩個ajax都成功返回資料才執行的商務邏輯})

 

寫一個自己的Promise,揭開Promise的神秘面紗

–Promise的規範

1.一個promise可能有三種狀態:等待(pending)、已完成(fulfilled)、已拒絕(rejected) 
2.一個promise的狀態只可能從“等待”轉到“完成”態或者“拒絕”態,不能逆向轉換,同時“完成”態和“拒絕”態不能相互轉換 
3.promise必須實現then方法(可以說,then就是promise的核心),而且then必須返回一個promise,同一個promise的then可以調用多次,並且回調的執行順序跟它們被定義時的順序一致 
4.then方法接受兩個參數,第一個參數是成功時的回調,在promise由“等待”態轉換到“完成”態時調用,另一個是失敗時的回調,在promise由“等待”態轉換到“拒絕”態時調用。同時,then可以接受另一個promise傳入,也接受一個“類then”的對象或方法,即thenable對象。

–promise原理分析 
可以看到promise的規範並不是很多,下面我們一邊分析promise一邊自己寫一個promise的實現。Promise實現的大致思路如下:

  建構函式Promise接受一個函數resolver,可以理解為傳入一個非同步任務,resolver接受兩個參數,一個是成功時的回調,一個是失敗時的回調,這兩參數和通過then傳入的參數是對等的。

其次是then的實現,由於Promise要求then必須返回一個promise,所以在then調用的時候會新產生一個promise,掛在當前promise的_next上,同一個promise多次調用都只會返回之前產生的_next。

由於then方法接受的兩個參數都是可選的,而且類型也沒限制,可以是函數,也可以是一個具體的值,還可以是另一個promise。下面是then的具體實現:

Promise.prototype.then = function(resolve, reject) {      var next = this._next || (this._next = Promise());      var status = this.status;      var x;      if(‘pending‘ === status) {          isFn(resolve) && this._resolves.push(resolve);          isFn(reject) && this._rejects.push(reject);          return next;      }      if(‘resolved‘ === status) {          if(!isFn(resolve)) {              next.resolve(resolve);          } else {              try {                  x = resolve(this.value);                  resolveX(next, x);              } catch(e) {                  this.reject(e);              }          }          return next;      }      if(‘rejected‘ === status) {          if(!isFn(reject)) {              next.reject(reject);          } else {              try {                  x = reject(this.reason);                  resolveX(next, x);              } catch(e) {                  this.reject(e);              }          }          return next;      }  };

 

參考文獻 
jQuery的deferred對象詳解 
JavaScript進階之路 
Javascript 中的神器

全面理解Javascript中Promise

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.