◆ これまで使ったことが全くなかった Promise.race を使う時が来た

何かの非同期処理を実行したときに一定時間過ぎても終わってないならエラー扱いにしたいときってありますよね
その非同期処理がタイムアウト機能に対応してれば 時間がすぎれば Promise が reject されたりしそうですが中にはタイムアウトに対応してなかったり 設定してるのになぜか終わってくれないライブラリもあったりします
そういうときのために自分でタイムアウトできるようなものを作ります

まずは基本のタイムアウトとか考えない非同期処理をする関数を用意します

async function p() {
const result = await fn()
return result
}

この関数は 非同期関数の fn を実行した結果を返すもので fn の処理が一定以上かかってるようならタイムアウトするようにします
やることは単純で自分で Promise を作って fn の結果を受け取ったら resolve し 受け取るより先に時間がくれば reject します

async function p(timeout) {
return new Promise(async (resolve, reject) => {
setTimeout(() => {
reject(new Error("timeout"))
}, timeout)
resolve(await fn())
})
}

fn にキャンセル処理があるなら reject 前に入れておきましょう

これで出来はしたのですが あんまり自分で Promise インスタンスを作りたくないです
コールバック関数必要ですし resolve/reject は自分で制御しなくていいほうが楽です

ということで別バージョンも作りました
こっちでは 一定時間後に reject される timeout 関数を用意しておきます

async function timeout(msec) {
return new Promise((_, reject) => setTimeout(reject, msec))
}

これを使って p 関数を作ると

async function p(timeout_ms) {
return Promise.race([fn(), timeout(timeout_ms)])
}

シンプルになりました
Promise.race は Promise の配列の中のどれかがおわったら resolve されるものです
fn のほうが先に終われば resolve になり timeout のほうが先に終われば reject となります
こっちだと p のような関数に毎回 new Promise しなくて済むので楽です