【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経過させるなどしないといけないfunctionasyncFunc(){returnnewPromise((resolve,reject)=>{setTimeout(()=>{try{resolve('成功')}catch(err){reject(err)}},3000)})}console.log(asyncFunc())=>Promise{<pending>}// 直接resolve、rejectedPromise.resolve('成功')=>Promise{'成功'}Promise.reject(newError('エラー'))=>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=>newError('エラー'))Promise.resolve(1).then(num=>console.log('resolve',num)).catch(err=>newError('エラー'))
【複数のPromiseを並行に処理してみる】
・ Promise.all
中のPromiseインスタンスが全部fulfilledになったら、その値でfulfilledを返す。
これだと各処理が平行に実行されるので効率がいい。
constall=Promise.all([1,Promise.resolve('成功'),Promise.resolve('fulfilled')])all=>Promise{[1,'成功','fulfilled']}
・Promise.allSettled
中のPromiseインスタンスがfulfilledかrejectedかに関わらずそれぞれの結果を返す。
とりあえず結果をきにせず平行に処理したい時に便利かも。
constallSettled=Promise.allSettled([Promise.resolve('成功'),Promise.reject(newError('エラー'))])allSettled=>Promise{[{status:'fulfilled',value:'成功'},{status:'rejected',reason:Error:エラー~(省略)
Node.jsでよく使うasync awaitもPromiseインスタンスをawaitの直前に置くことで実装できるように設計されているためPromiseの理解が重要。