Promise
Promise
は非同期処理においてコールバック (事後処理/エラー処理) を登録しておき、処理に応じて呼び出す仕組み。メソッドチェーンにより順次処理を連結することができる。
new
を使ってコンストラクタを呼び出して Promise
オブジェクトを生成する。
new Promise( /* executor */ function (resolve, reject) { ... } )
Promise
オブジェクト生成の際に executor
関数は即時に実行される。(Promise
コンストラクタがオブジェクトを返すよりも前に executor
は実行される。)
executor
は通常、非同期な作業の実行が完了した際に resolve
関数 (成功した場合) もしくは reject
関数 (エラーが発生した場合) のいずれか一方を呼び出す。
resolve
関数と reject
関数は呼び出されると Promise
に対してそれぞれ「解決 (resolve)」もしくは「拒否/棄却 (reject)」を行う。
executor
関数でエラーが投げられた場合、Promise
は reject
される。
executor
の返り値は無視される。(返り値は意味を持たない。)
doSomething()
が Promise
を返す場合に、then
関数を連結して呼び出すことで成功した場合と失敗した場合の2種類のコールバックを指定することができる。
doSomething().then(successCallback, failureCallback)
戻り値の Promise
に順次コールバックを追加して、Promise
チェーンを記述することができる。(次の処理を then
関数で連結するために各処理で Promise
オブジェクトを返す。最終処理は Promise
オブジェクトを返す必要はない。)
doSomething() .then(function (result) { return doSomethingElse(result) }) .then(function (newResult) { return doThirdThing(newResult) }) .then(function (finalResult) { console.log('Got the final result: ' + finalResult) }) .catch(failureCallback)
catch(failureCallback)
は then(null, failureCallback)
のショートハンド。
アロー関数を使って、Promise
チェーンを次のように記述できる。
new Promise((resolve, reject) => { console.log('Initial') resolve() }) .then(() => { throw new Error('Something failed') console.log('Do this') }) .catch(() => { console.log('Do that') }) .then(() => { console.log('Do this whatever happened before') }) // => printed result: // Initial // Do that // Do this whatever happened before
参考:
Promise による非同期処理の書き方 | 30歳からのプログラミング
Promise と仲良くなって気持ち良く非同期処理を書こう – Qiita
JavaScript の Promise: 概要 | Google Developers
JavaScriptプログラミング講座 Promise について | HAKUHIN’s home page
Node.js を使った非同期処理の理解 | Solutionware 開発ブログ
メソッドチェーン
参考:
Promise のメソッドチェーンの使い方まとめ – Qiita
シンタックスシュガー async / await の使い方
同期バージョン
try { let result = syncDoSomething() let newResult = syncDoSomethingElse(result) let finalResult = syncDoThirdThing(newResult) console.log(`Got the final result: ${finalResult}`) } catch(error) { failureCallback(error) }
非同期バージョン
async function foo() { try { let result = await doSomething() let newResult = await doSomethingElse(result) let finalResult = await doThirdThing(newResult) console.log(`Got the final result: ${finalResult}`) } catch(error) { failureCallback(error) } }
参考:
非同期関数の書き方
async function myAsyncFunction() { try { const fulfilledValue = await promise } catch (rejectedValue) { // error handling } }
関数定義の前に async
キーワードを使用すると、その関数内で await
を使用できる。 Promise
を await
する場合、この関数はブロックすることなく Promise
が完了状態になるまで一時停止する。Promise
が解決すると値が返される。Promise
が棄却すると棄却された値がスローされる。
参考:
非同期関数 – Promise をわかりやすくする | Google Developers
finally / always
参考:
Promise.prototype.finally() | MDN
Execute something regardless of resolve / reject? – Stack Overflow
Promise.all
参考:
Promise と async / await で複数の非同期処理の完了を待機する | abcdefg…..
並列処理/直列処理
並列処理
- Promise.all()
直列処理
then()
をチェインするArray.prototype.reduce()
を使う- ジェネレータを使う
async
/await
を使う
reduce
を使った直列処理
let itemIDs = [1, 2, 3, 4, 5] itemIDs.reduce((promise, itemID) => { return promise.then(_ => api.deleteItem(itemID)) }, Promise.resolve())
参考:
最近の js 非同期処理 Promise と Generator の共存 – Qiita
Promise を Array#reduce で直列に実行する | 四角革命前夜
Promise を返す関数の直列実行における reduce の利用と注意点 – Qiita
Promise を複数の直列処理と並列処理を組み合わせる – Qiita
Why Using reduce() to Sequentially Resolve Promises Works | CSS-Tricks
ES6 Promises: Patterns and Anti-Patterns | DataFire.io
Resolving Promises Sequentially | Hacker Noon
Serial Promise Execution with JavaScript | derp turkey
Running Promises in Serial with Array.reduce() | Decembersoft Inc.
Resolve promises one after another (i.e. in sequence)? – Stack Overflow
Promise と Callback の両方に対応する関数
参考:
Promise と Callback の両方に対応する関数の書き方 | Tokyo Otaku Mode Blog
Promise.defer / Deferred
***OBSOLATE***
ECMAScript では採用されなかった。使用するにはポリフィル (PromiseDefer.js など) が必要。
参考:
Unhandled Promise Rejection
参考:
Node.js で捕捉されなかった Promise 内の例外をスタックトレースで表示する – Qiita
Promise Error Handling (slide) | azu.github.io
How to prevent your Node.js process from crashing | DailyJS
loud-rejection
参考:
hard-rejection
参考:
PromiseDefer.js
参考:
Deferred
参考:
medikoo/deferred: Modular and fast Promises implementation for JavaScript – GitHub
node-promise-retry
非同期処理を失敗時に指定した回数だけリトライする。
参考: