広告の限界を超える|セールス
広告の限界を超える|セールス
2015.01.06

Node.js完全初心者が、モジュールを作成して、ディレクトリを非同期で読み取り、ファイルをコンソールに出力する方法

エリカ

こんにちは。ディレクターのエリカです。

こちらは、Node.jsという言葉を聞いて「何となくはわかるけど、実際にどんなものか触ったことがない」という初心者の方に向け、チュートリアル用モジュール「learnyounode」でエクササイズをしていくコーナーの第6回目です。

前回は、ディレクトリを非同期で読み取りファイルのリストを出力する問題について紹介しました。
今回は、これまでのエクササイズで便利だった「モジュール」というものを作ることになります。

Node.jsを勉強したいと思っている人のキッカケや第一歩になれば幸いです。それでは早速はじめていきましょう

MAKE IT MODULAR(Exercise 6 of 13)

「learnyounode」のインストールがまだの方は、こちらからどうぞ。

問題

※今回の問題の内容は前回とほぼ同様です。しかし今回は、モジュールの概念を取り入れてみてください。そうすると、2つのファイルを作成する必要があるでしょう。

あるディレクトリの中にあるファイルを、拡張子でフィルタリングして表示するプログラムを作成してください。
コマンド実行時には、ディレクトリへのパスが第一引数に、フィルタする拡張子が第二引数に与えられるものとします。

例えば、第二引数に「txt」が与えられた場合には、「.txt」で終わるファイルのみを表示する必要があります。

ファイルのリストは、ファイル名を一行毎に表示する形式にしてください。また、今回は非同期で処理を行ってください。

上記の大半を行うモジュールを作成してください。そのモジュールは、3つの引数をとる1つの関数を提供します。引数は、ディレクトリ名、拡張子、そして、コールバック関数です。拡張子はプログラムに渡されるものを変更せずにそのまま渡すようにしてください。モジュール内で、フィルタリングする際に正しい形に整形するのは構いません。

コールバック関数は、慣用的な(これまでにもあったような)node(err, data)という形式にしてください。エラーがなければ、errにはnullが、dataには利用したいデータが渡されるというものです。今回の場合でいえば、フィルターするファイルのリストが配列で渡されることになるかと思います。

モジュール内では出力しないでください。

モジュールの要件をまとめると、以下のようなものになります。

  • モジュールは指定した引数を受け取れる1つの関数を提供してください。
  • 成功時も失敗時もただ一度だけコールバック関数を実行してください。
  • グローバル変数や標準出力に影響を与えないようにしてください。
  • 発生しうる全てのエラーをコールバック関数に渡してください。

ヒント

モジュールを作成するには、下記のような記述を含んだファイルを作成します。

module.exports = function (args) { /* ... */ }

作成したモジュールを利用する場合は、いつものように利用したいファイルでrequire()を利用します。
これまでのものと違うのは、ファイルのパスを明記する必要があることくらいです。例えば、今回のモジュールをmymodule.jsという名前で作成したのであれば、以下のようになります。

var mymodule = require('./mymodule.js')



※ここでは「.js」の部分についてはオプションです。しばしば省略した形を目にしたことかと思います。

これで、mymoduleを関数として利用できる様になります。

また、エラーチェックとそのコールバック利用の慣用的な書き方を例示しておきます。

function bar (callback) {
      foo(function (err, data) {
        if (err)
          return callback(err) // early return

        // ... no error, continue doing cool things with `data`

        // all went well, call callback with `null` for the error argument

        callback(null, data)
      })
    }

解答

プログラム本体はこちら。

var filterFn = require('./solution_filter.js') // モジュールの読み込み

    var dir = process.argv[2] // ディレクトリのパス
    var filterStr = process.argv[3] // フィルタする拡張子

    // モジュールが提供する関数の実行
    filterFn(dir, filterStr, function (err, list) {

        // エラーがあれば
      if (err)
        return console.error('There was an error:', err)

    // ファイルのリストを一行ずつ出力
      list.forEach(function (file) {
        console.log(file)
      })
    })

作成するモジュールはこちら。

var fs = require('fs') // fsモジュールの読み込み
    var path = require('path') // pathモジュールの読み込み

// 関数の提供
    module.exports = function (dir, filterStr, callback) {

      fs.readdir(dir, function (err, list) {
        if (err)
          return callback(err)

        list = list.filter(function (file) {
          return path.extname(file) === '.' + filterStr
        })

        callback(null, list)
      })
    }

まとめ

いかがでしたか?
モジュールとして作成しておくと、別の機会でも再利用できるなど非常に便利です。また、公式のもの以外にも、さまざまな人の手によって多種多様なモジュールが既に作成され、配布されているので、気になるモジュールを見つけたら利用してみるのもいいかもしれません。

次回は、いよいよ「HTTP CLIENT」になります。

 

【「learnyounode」エクササイズシリーズ】

  1. Node.js完全初心者向けチュートリアル用モジュール「learnyounode」を使ってみよう
  2. Node.js完全初心者のための、合計値を計算し、コンソールに出力する方法
  3. Node.js完全初心者が、ファイルを同期で読み取り、行数をコンソールに出力する方法
  4. Node.js完全初心者が、ファイルを非同期で読み取り、行数をコンソールに出力する方法
  5. Node.js完全初心者が、ディレクトリを非同期で読み取り、ファイルをコンソールに出力する方法