書いてから思ったのですが、下から読んだ方がいいかも。
Promise 以前の状況
例えば node.js で 'x' という名前のファイルの stat を取得したい場合
sample.js
constfs=require('fs')fs.stat('x',(er,stat)=>{if(er)console.error(er)elseconsole.log(stat)})
という風にやってたと思います。
ファイルが複数の場合
複数のファイル、例えば 'x', 'y' という名前のファイルの stat を取得してから何かやりたいような場合、時間のかかる逐次処理でよければ
sample.js
constfs=require('fs')conststats=[]fs.stat('x',(er,stat)=>{if(er)console.error(er)else{stats.push(stat)fs.stat('y',(er,stat)=>{if(er)console.error(er)else{stats.push(stat)console.log(stats)}})}})
並行にしたい場合はちょっと苦しいテクニックを使って
sample.js
constfs=require('fs')conststats=[null,null]fs.stat('x',(er,stat)=>{if(er)console.error(er)else{stats[0]=statif(stats[1])console.log(stats)}})fs.stat('y',(er,stat)=>{if(er)console.error(er)else{stats[1]=statif(stats[0])console.log(stats)}})
のようにする必要がありました。ちょっと大変です。特にファイルの数が増えたりしたら。
Promise 以降
fs.stat を Promise 化すると上のような大変さがなくなります。
Promise 化
util.promisify を使う
sample.js
constfs=require('fs')const{promisify}=require('util')promisify(fs.stat)('x').then(_=>console.log(_)).catch(_=>console.error(_))
素でやる
util.promisify がある今となってはもうやることはないと思いますが、参考までに。
sample.js
constfs=require('fs')newPromise((rs,rj)=>fs.stat('x',(er,stat)=>er?rj(er):rs(stat))).then(_=>console.log(_)).catch(_=>console.error(_))
ファイルが複数の場合
Promise.all を使う
Promise の配列を作って Promise.all に渡してやります。配列の中のすべての Promise が解決されるか、どれかがリジェクトされるまで待ちます。
sample.js
constfs=require('fs')const{promisify}=require('util')Promise.all(['x','y'].map(_=>promisify(fs.stat)(_))).then(_=>console.log(_)).catch(_=>console.error(_))
関数化してみる
sample.js
constfs=require('fs')const{promisify}=require('util')constStats=files=>Promise.all(files.map(_=>promisify(fs.stat)(_)))Stats(['x','y','z']).then(_=>console.log(_)).catch(_=>console.error(_))
最後に
Promise.all を使わない手はありませんね!