標籤: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