Promise
code:promiseheaven.js
f(arg)
.then(g)
.then(h)
.then(result => { console.log(result); })
.catch(err => { /* エラーハンドリング */ });
Promiseによる非同期関数は Promise インスタンスを同期的に返す
Promiseには3つの状態がある
結果が未確定の pending
処理に成功した fulfilled
処理に失敗した rejected
fulfilledとrejectedを合わせてsettledと呼ぶ
こんな感じ
code:pr.js
const 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 インスタンスに詰めて返す