當前位置:
首頁 > 最新 > promise的使用

promise的使用

本文主要介紹一下 在一些場景下的使用,同時還有對 規範的一點個人理解。原本是想總體的講一下JavaScript非同步編程的內容,後由於內容很多,能力有限,目前計劃分成幾部分。

Promise A+ 規範

為了更好的表述,我把 規範拆成了兩部分介紹:

第一部分規範:

一個 的當前狀態必須為以下三種狀態中的一種:等待態( )、執行態( )和拒絕態( )。

一個 必須提供一個 方法以訪問其當前值、終值和據因。

promise.then(onFulfilled, onRejected);

第二部分規範:

方法需要 一個新的 出來,如下:

promise2 = promise1.then(onFulfilled, onRejected);

如果 不是函數且 成功執行, 必須成功執行並返回相同的值;如果 不是函數且 拒絕執行, 必須拒絕執行並返回相同的據因。

如果 本身狀態變更到 之後,返回調用 , 的解析值 ,與新的 進行 的解析過程 , 的取值不同,有不同的情況:

若 為一個 ,則使 接受 的狀態:

var promise2 = new Promise(function(resolve, reject){ resolve(); }).then(function(data){ // 對應於 x 的返回值 return new Promise(function(resolve, reject){ resolve( x = promise ); }); }); promise2.then(function(data){ // 列印 x = promise console.log(data); });

為了看的清晰一點,我把鏈式拆開了,正常是這樣子:

new Promise(function(resolve, reject){ resolve(); }).then(function(data){ // 對應於 x 的返回值 return new Promise(function(resolve, reject){ resolve( x = promise ); }); }).then(function(data){ // 列印 x = promise console.log(data); });

若 為一個對象或者函數,如果有 方法,將會執行 方法, 方法 指向 本身,如下:

new Promise(function(resolve, reject){ resolve(); }).then(function(data){ // 對應於x的返回值 return { a: 1, then: function(resolve, reject){ // 列印 1 console.log(this.a); resolve(); } }; }).then(function(data){ // 列印 2 console.log(data.a); });

如果 沒有 方法,那麼, 將會做為值來 滿足 ,如下:

new Promise(function(resolve, reject){ resolve(); }).then(function(data){ // 對應於x的返回值 return { a: 1 }; }).then(function(data){ // 列印 1 console.log(data.a); });簡單實現的 Promise 對象

這是一個簡單實現的 對象,根據我在上面自己分出來的第一部分規範,實現了『有狀態』和 方法。

function Promise(fn){ var state = pending ; var value; var deferred; function resolve(newValue){ value = newValue; state = resolved ; if(deferred) { handle(deferred); } } function handle(onResolved){ if(state === pending ) { deferred = onResolved; return; } onResolved(value); } this.then = function(onResolved){ handle(onResolved); }; fn(resolve); }

當 的時候:

執行 並把 resolve 方法交給 準備調用

同步執行 方法,將 作為參數調用 方法

如果 同步執行,那麼 變更為 ,緊接著 也立即執行

如果 沒有同步執行,那麼 依舊是 ,那麼將 的引用保存起來,等到 非同步執行的時候,再調用 方法

new Promise(function fn1(resolve){ setTimeout(function(){ resolve( eventual value ); }, 1000); }).then(function fn2(data){ // 等待 1000ms 後,列印 eventual value console.log(data); });

接下來根據我在上面自己分出來的第二部分規範,下面的實現增加了鏈式和穿透的特性。

function Promise(fn){ var state = pending ; var value; var deferred = null; function resolve(newValue){ // 這部分是新增的,見注一 if(newValue && typeof newValue.then === function ) { newValue.then(resolve); return; } value = newValue; state = resolved ; if(deferred) { handle(deferred); } } function handle(handler){ if(state === pending ) { deferred = handler; return; } // 這部分是新增的,見注二 if(!handler.onResolved) { handler.resolve(value); return; } var ret = handler.onResolved(value); handler.resolve(ret); } this.then = function(onResolved){ return new Promise(function(resolve){ handle({ onResolved: onResolved, resolve: resolve }); }); }; fn(resolve); }

由於 永遠返回一個新的 對象,導致每次都至少有一個 對象被創建、解決然後被忽略,這就產生了一定程度了內存浪費。

方法返回新的 對象,這個 要 的值是 的返回值。 函數的最後兩行體現了這一點, 對象保存了 回調函數和 函數的引用。在鏈式調用中保存了多個 函數的拷貝,每一個 對象的內部都擁有一個自己的 方法,並在閉包中運行。 這建立起了第一個 與第二個 之間聯繫的橋樑。

new Promise(function(resolve){ setTimeout(function(){ resolve( promise1 eventual value ); }, 1000); }).then(function(data){ // 等待 1000ms 後,列印 promise1 eventual value console.log(data); return { then: function(resolve){ setTimeout(function(){ resolve( promise2 eventual value ); }, 1000); } } }).then(function(data){ // 等待 2000ms 後,列印 promise2 eventual value console.log(data); });

注一: 方法內部的返回值可以是 對象, 如果是要通過 方法獲取終值,對應第二部分規範第4和5條。

注二: 裡面第一個 會被跳過, 也會用上一個 返回的終值來傳遞,對應第二部分規範第2條。

new Promise(function(resolve){ setTimeout(function(){ resolve( promise1 eventual value ); }, 1000); }).then().then(function(data){ // 等待 1000ms 後,列印 promise1 eventual value console.log(data); });

上面的代碼一直忽略掉一個問題,錯誤處理,這裡不做引述,原因是我覺得實現方式類似,需要注意的點會在下面講。

Promise 使用Promise.all()

當我們想使用 的時候,我們可以使用 。 以一個 對象組成的數組為輸入,返回另一個 對象。這個對象的狀態只會在數組中所有的 對象的狀態都變為 的時候才會變成 。可以將其理解為非同步的 循環。注意的是,如果輸入的一系列 對象中,有一個的狀態變為 ,那麼 返回的 對象的狀態也會變為 。

var array = []; for (var i = 0; i

可以將同步代碼包裝成 形式,後面可以加 或者 ,我覺得在封裝介面的時候很適用。

new Promise(function(resolve, reject){ resolve(someSynchronousValue); }).then(...);

精簡為:

Promise.resolve(someSynchronousValue).then(...);cacth() 和 then(null, …) 並不完全相同

下面兩個代碼片段是等價的:

somePromise().catch(function(err){ // handle error }); somePromise().then(null, function(err){ // handle error });

但是,這並不意味著下面的兩個代碼片段是等價的

somePromise().then(function(){ return someOtherPromise(); }).catch(function(err){ // handle error }); somePromise().then(function(){ return someOtherPromise(); }, function(err){ // handle error });

結論就是,當使用 , 不會捕獲在 中拋出的錯誤。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 推酷 的精彩文章:

WidgetLayout:一組繼承於 ViewGroup 的自定義容器集合
關於編程一些雜亂的想法
聊聊「二叉搜索樹」的那些事兒
Flink-Table-SQL系列之source
探索 Swift 4 中新的 String API

TAG:推酷 |

您可能感興趣

A Forever Promise 永遠的應許
promise、async和await之執行順序的那點事
callback Promise async await 非同步回調 案例
嗨,還記得那年我們的約定嗎?Sorry,I broke my promise
#新勢力發售# 不只是一個運動員 |Nike LeBron 16 「I Promise」? | Xsneaker
Nike LeBron 16 「I Promise
ES6——Promise使用經驗
Promise介面是AngularJS組織API的基礎
有教無類!LeBron James 首間成立學校 I Promise 落座阿克倫
ES6 Promise 對象
NPM酷庫:pify 將非同步函數Promise化
近賞丨全新 「I Promise」 配色 Nike LeBron 16
全新慈善配色!Nike LeBron 16 「I Promise」 即將發售!
Promise為媒體用戶推出Pegasus 32系列存儲解決方案
Promise實現原理
年底發售!彩虹大底 Nike LeBron 16 「I Promise」 實物曝光!
勒布朗慈善配色!細節超豐富的彩虹 LeBron 16 「I Promise」?即將發售!
勒布朗慈善配色!細節超豐富的彩虹 LeBron 16 「I Promise」? 即將發售!
數組的遍歷你都會用了,那Promise版本的呢
勒布朗慈善配色!細節超豐富的彩虹 LeBron 16 「I Promise」 即將發售!