Promise
promiseheaven.jsf(arg)
.then(g)
.then(h)
.then(result => { console.log(result); })
.catch(err => { /* エラーハンドリング */ });
Promiseによる非同期関数は Promise
インスタンスを同期的に返す
Promiseには3つの状態がある
結果が未確定の pending
処理に成功した fulfilled
処理に失敗した rejected
fulfilledとrejectedを合わせてsettledと呼ぶ
こんな感じ
pr.jsconst divAfter = (ms, x, y) => {
return new Promise((resolve, reject) =>
setTimeout(() => {
try {
resolve(x / y);
} catch (e) {
reject(e);
}
}, ms)
);
};
divAfter(1000, 10n, 10n).then((value) => {
console.log(value);
});
divAfter(1000, 10n, 10n).catch((err) => {
console.error(`err: ${err}`), process.exit(1);
});
即座にsettledなPromiseインスタンスを生成する方法もある
Promise.resolve()
Promise.reject()
非同期処理の逐次実行はインスタンスメソッドで行う
promise.then()
コールバック onFulfilled
onRejected
を登録する
promise.then(value => {成功時の処理}, err => {失敗時の処理})
Promiseがfulfilledになったとき onFulfilled
が呼ばれる
このとき then
の返り値は onFulfilled
で返した値で解決される新しいPromiseインスタンス
Promise.resolve(1).then(value => value + 1)
の返り値は 2
に解決されるPromise
Promise.resolve(1).then(value => value + 1, err => \
${err.message}\ )
も同じ
Promiseがrejectedになったとき onRejected
が呼ばれる
このとき then
の返り値は onRejected
の返り値で解決されたPromiseインスタンスになる
Promise.reject(new Error("error!")).then(value => value + 1, err => \
${err.message}\ )
の返り値は "error!"
に解決されるPromsie
onRejected
を省略した場合エラーがそのまま渡る
Promise.reject(new Error("error!")).then(value => value + 1)
は unhandled rejection になる
onFulfilled
onRejected
でエラーがthrowされると then
の返り値はそれでrejectされる
Promise.resolve(1).then(_ => throw new Error("hoge"))
はErrorインスタンスでreject
Promise.reject(1).then(_ => _, throw new Error("hoge"))
もErrorインスタンスでreject
onFulfilled
onRejected
でPromiseを返す、つまりPromiseのネストを試みると潰される
Promise.resolve(1).then(value => Promise.resolve(value + 1))
は 1
に解決されるPromise
(t: T) => Promise<R>
みたいな関数 (非同期関数) をthenに渡して処理をつなげられる
promise.catch(onRejected)
promise.then(undefined, onRejected)
と等価
promise.then(f).then(g).then(h).catch(errorHandling)
とすればすべてのエラーをerrorHandlingで捕捉できる
promsie.finally(onFinally)
Promiseがsettledになったときコールバックを実行する
やはり返り値は新しいPromiseインスタンス
コールバックからPromiseを返した場合、finallyの返り値のPromiseはそれを待つ
finallyの返り値のPromiseが解決される値はfinallyを呼び出したインスタンスと同じになる
生の値だろうとPromiseだろうと、コールバックの返り値は影響しない
finallyのコールバックがエラーを発生した場合はfinallyの返り値のPromiseがそれで拒否される
promise.finally(() => { throw new Error(); })
や promise.finally(() => Promise.reject(new Error()))
then
catch
fanally
のコールバックはかならず非同期的に実行される
非同期処理の並行実行は globalThis.Promise
に生えた関数で行う
イテラブルを引数にとりPromiseを返す
Promise.all
すべてのPromiseがfulfilledになったときそれらを配列で持ったfulfilledなPromiseになる
1つでもrejectedになると他を待たず即座にその値でrejectする
Promise.race
一番早くsettledになったPromiseをそのまま返す
空のイテラブルを渡すと永遠にpending
非同期処理とt秒後に拒否されるPromiseを並べれば、非同期処理がt秒までに終わらかなった場合rejectされるタイムアウト処理が作れる
Promise.allSettled
すべてのPromiseがsettledになったらそれらの結果を配列に詰めて返す
結果はTypeScriptでいうと { status: "fulfilled", value: T } | { status: "rejected", reason: unknown }
Promise.any
一番早くfulfilledになったPromiseをそのまま返す
全部rejectedだったらそれを AggregateError
インスタンスに詰めて返す