【Promiseとは】
Promiseはrejectedかfulfilledという結果が帰ってくることを約束してくれる。
そのため、それらに対するハンドリングがしやすいといったメリットがあると勉強していて感じた。実際、Node.jsの各メソッドをPromiseインスタンスに変換できるようなものが導入されたりとそのうちPromiseの規格に統一されるかもしれない。
【Promiseの挙動】
Promiseは、Promiseインスタンスを返す。
その時、Promiseインスタンスは最終的に、rejectedかfulfilledを返すが、それは以下のようにpendingな状態をreject()かresolve()で解決しないといけない。
pending
↓
/ \
reject() resolve()
↓ ↓
rejected fulfilled <= これらの状態をsettledという
【Promiseインスタンスをsettled状態にしてみる】
まずPromiseはnew Promise()
のようにして一度pendingな状態にする方法と、
pending状態を経ずに直接fulfilled、rejected状態にする2パターンある。
// 一度pendingにする
// settledにするには一度変数に入れて、setTimeoutで3000経過させるなどしないといけない
function asyncFunc(){
return new Promise((resolve, reject) => {
setTimeout(() => {
try{
resolve('成功')
}catch(err){
reject(err)
}},3000)
})
}
console.log(asyncFunc()) => Promise { <pending> }
// 直接resolve、rejected
Promise.resolve('成功') => Promise { '成功' }
Promise.reject(new Error('エラー')) => Promise { <rejected> Error: エラー ~~(省略)
【settled状態を利用して次の処理をおこなう】
.then()、.catch()、を使えば、Promiseインスタンスがsettledになったら、実行するコールバック処理を設置できる。
以下の処理は、Promiseが1でfulfilled状態になり、その結果を.then()のnumで受け取っている。
Promiseでコールバックヘルが解決できるのはこういったことができるからだ。
Promise.resolve(1)
.then(num => console.log('resolve', num))
上記の.then()は省略されており、第二引数には.then()で起きたエラーの処理を受け取れるようになっている。しかし、これは.then()が多くなると長くなる。
.catch()を最後につけることで.then()で起きたエラーを全て一箇所で受け取れる。
// 同じことをしている
Promise.resolve(1)
.then(
num => console.log('resolve', num),
err => new Error('エラー')
)
Promise.resolve(1)
.then(num => console.log('resolve', num))
.catch(err => new Error('エラー'))
【複数のPromiseを並行に処理してみる】
####・ Promise.all
中のPromiseインスタンスが全部fulfilledになったら、その値でfulfilledを返す。
これだと各処理が平行に実行されるので効率がいい。
const all = Promise.all(
[1,Promise.resolve('成功'), Promise.resolve('fulfilled')]
)
all => Promise { [ 1, '成功', 'fulfilled' ] }
####・Promise.allSettled
中のPromiseインスタンスがfulfilledかrejectedかに関わらずそれぞれの結果を返す。
とりあえず結果をきにせず平行に処理したい時に便利かも。
const allSettled = Promise.allSettled([
Promise.resolve('成功'), Promise.reject(new Error('エラー'))
])
allSettled => Promise {[
{ status: 'fulfilled', value: '成功' },
{ status: 'rejected',
reason: Error: エラー ~ (省略)
Node.jsでよく使うasync awaitもPromiseインスタンスをawaitの直前に置くことで実装できるように設計されているためPromiseの理解が重要。