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
非同期処理を失敗時に指定した回数だけリトライする。
参考: