JS Promise 的套路
在 Promise 加入 ES 標準前,俺一直以來處理 async 的方式是使用一些第三方的實現。 比如:
Promise 加入 ES6 標準后就盡量使用 Promise。
- 好處:
- 減少第三方的依賴
- Promise 的實現相對 async 之類的基於 callback 會有些優勢。
比如: 沒有忘記調用 callback 或者 多次 callback 的問題; 也可以處理 throw exception 的情況。
- 壞處:
- Promise chain 連來來去,如果複雜度高,有時自己會暈。 有時甚至比 callback hell 更加讓人頭暈。
套路整理
為了避免日常錯誤,俺把日常會用到的一些套路 ( patterns ) 都演練了一下。 日常用的套路可以分爲: 串行執行 (series); 並行執行 (parallel); 還有一种複雜一點的 retry 有時會用到。
下面所提到的那些測試的代碼都放在了 Github 上:
Series: node test/test_series.js
- 處理 Task A, B, C。 A, B, C 順序執行, 都結束則執行 Final。
- 處理 Task A, B, C。 A, B, C 會順序執行, 如果都結束則執行 Final。 A, B, C 有失敗則直接執行 Final, 並且報 error。
- 處理 Task A, B, C。 A, B, C 會順序執行, 如果都結束則執行 Final。 A, B, C 有失敗根據需要可以忽略,只把 Error 記錄。 依舊繼續往下跑到 Final 。
Parallel: node test/test_parallel.js
- 處理 Task A, B, C。 A, B, C 並行執行, 都結束則執行 Final。
- 處理 Task A, B, C。 A, B, C 並行執行, 都結束則執行 Final。 如果有 error 則記錄下來,到最後一起返回給 Final。
Race - node test/test_race.js
Race 和 Parallel 一樣用於處理並行任務。區別在於處理並行任務時, Race 只會等到第一個任務成功或失敗,而不等所有的任務結束。 這種套路經常用於 Timeout,比如 Connection 和 Timer 作爲 2 個 Tasks。
- 比如 Task A, B。 A 需要 3 seconds; B 需要 1 second , 最後 Final 會等到 B 結束。
Retry node test/test_retry.js
固定次數的 Retry 用 Promise 實現比較方便。
- Retry Task A 3 次 后成功:
- Retry Task A 3 次依舊失敗:
Until - node test/test_until.js
不固定次數的 retry 用 Promise 實現也不是很方便。
實現了一個在 test/test_until.js
裏,也不算很好。
exports.untilPassed()
:- 最大 retry 1000 次,每次延遲 10ms
- 100 次調用后, retryTask 會成功
exports.untilErr()
:- 最大 retry 1000 次,每次延遲 10ms
- 這個 retryTask 永遠不會成功
- 1000 次后 這個 until 會報錯結束
最後
一些有關于 JS Promise 或者 Async 的資料:
-
async 文檔中的那些 Patterns, 對於 JS Async 有比較好的抽象。
-
You Don’t Know JS (book series) 中的 “Async & Performance” 和 “ES6 & Beyond” 兩本。
-
Mozilla MDN 中對於 Promise 的説明: MDN Promise
-
中文的 JS Promise 迷你书。有對 Promise 的基礎介紹。 JS Promise 迷你书
blog comments powered by Disqus