はじめに
サードパーティライブラリのPromiseな関数をタイムアウトさせたい場面があり、
AbortControllerを使わずPromise.race()でシンプルに実装してみました。
Promise.race()とは?
Promise.race() は静的メソッドで、入力としてプロミスの反復可能オブジェクトを受け取り、単一の Promise を返します。この返されたプロミスは、最初に決定したプロミスの最終的な状態で決定されます。
引用元 : MDN - Promise.race()
簡単に言えば、複数のPromiseを競わせて一番非同期処理が早い結果を返して、残りの遅い処理はキャンセルするという事になります。
一番に非同期処理が終わったらreject
されている場合も返却される点に注意が必要です。
実装例
libFunction
の非同期処理が2秒以上かかる場合は、timeoutPromise
の結果が返される事で、
実質的にlibFunctionをキャンセルしています。
※ 今回はPromiseの返却値の型をstringにしていますが、それぞれ返却値に応じた型を指定すれば大丈夫です。
import libFunction from 'FOO PATH' // 非同期なライブラリ関数をインポート
async function doTask(){
const TIMEOUT = 2000 // タイムアウト時間 (Milliseconds)
// ライブラリのPromise関数をラップ
const wrappedLibFunction = new Promise<string>(resolve =>
libFunction().then((text) => {
resolve(text) // ライブラリのPromise関数の結果をresolveします。
})
)
// キャンセルに使うPromise処理
const timeoutPromise = new Promise<string>(resolve =>
setTimeout(() => resolve('2秒後に返すtimeoutの内容'), TIMEOUT),
)
// 完了が早い方のPromise関数が返り値になります。
const result = await Promise.race([wrappedLibFunction, timeoutPromise])
return result
}
まとめ
AbortControllerを使わないで遅い非同期処理のキャンセルをPromise.race()で実装しました。
AbortControllerの方が細かい設定等が可能ですが、コードも複雑になりがちなので、
重要度が低めの非同期処理のキャンセルはPromise.race()で実装しても良いかもしれません。
参考文献