任意の大きなファイルセットに対して、任意のコストのかかる作業を実行したいと思います。進捗状況をリアルタイムで報告し、すべてのファイルが処理された後に結果を表示したいと思います。私の表現に一致するファイルがない場合は、エラーをスローしたいと思います。
すべてのテストファイルをロードし、それらを(順不同で)実行し、進行状況をリアルタイムでレポートし、すべてのテストが完了した後に集計結果を表示するテストフレームワークを作成することを想像してみてください。
このコードをブロッキング言語(たとえばRubyなど)で記述するのは非常に簡単です。
結局のところ、この一見単純なタスクをノードで実行するのに問題がありますが、非同期のイベントベースのIOを実際に利用しています。
私の最初の設計は、各ステップを連続して実行することでした。
- すべてのファイルをロードし、処理するファイルのコレクションを作成します
- コレクション内の各ファイルを処理します
- すべてのファイルが処理されたら結果を報告します
このアプローチは機能しますが、プログラムの計算コストの高い部分がすべてのファイルIOの完了を待機するため、私には適切ではないようです。これは、ノードが回避するように設計された種類の待機ではありませんか?
私の2番目の設計は、ディスク上で非同期的に検出された各ファイルを処理することでした。議論のために、次のようなメソッドを想像してみましょう。
eachFileMatching(path, expression, callback) {
// recursively, asynchronously traverse the file system,
// calling callback every time a file name matches expression.
}
そして、このメソッドのコンシューマーは次のようになります。
eachFileMatching('test/', /_test.js/, function(err, testFile) {
// read and process the content of testFile
});
この設計はIOを操作する非常に「ノード」の方法のように感じますが、2つの大きな問題があります(少なくとも私のおそらく誤った実装では)。
- すべてのファイルがいつ処理されたかわからないので、いつ結果をアセンブルして公開するかわかりません。
- ファイルの読み取りは非ブロッキングで再帰的であるため、ファイルが見つからなかったかどうかを知る方法に苦労しています。
私は単に何か間違ったことをしていること、そして他の人々が2番目のアプローチを機能させるために使用する合理的に単純な戦略があることを望んでいます。
この例ではテストフレームワークを使用していますが、これとまったく同じ問題にぶつかる他のさまざまなプロジェクトがあります。ノード内のファイルシステムにアクセスするかなり洗練されたアプリケーションを作成する人もいると思います。