Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8691

fs.stat を Promise 化して複数のファイルの stat を一気に取る。

$
0
0

書いてから思ったのですが、下から読んだ方がいいかも。

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 を使わない手はありませんね!


Viewing all articles
Browse latest Browse all 8691

Trending Articles