## 要求
這個問題和前面一個一樣,但是這次需要使用模塊。將需要創建兩個文件來解決這個問題。
編寫一個程序來打印出所給文件目錄的所含文件的列表,并且以特定的文件名后綴來過濾這個列表。這次將會提供兩個參數,第一個參數是要列舉的目錄,第二個參數是要過濾的文件擴展名。在終端中打印出過濾出來的文件列表(一個文件一行)。此外,必須使用異步 I/O。
需要編寫一個模塊文件去做大部分的事情。這個模塊必須導出(export)一個函數,這個函數將接收三個參數:目錄名、文件擴展名、回調函數,并按此順序傳遞。文件擴展名必須和傳遞給程序的擴展名字符串一模一樣。也就是說,請不要把它轉成正則表達式或者加上”.”前綴或者做其他的處理,而是直接傳到模塊中去,在模塊中,可以做一些處理來使過濾器能正常工作。
這個回調函數必須以 Node 編程中慣用的約定形式(err,data)去調用。這個約定指明了,除非發生了錯誤,否則所傳進去給回調函數的第一個參數將會是 null,第二個參數才會是數據。在本題中,這個數據將會是過濾出來的文件列表,并且是以數組的形式。如果接收到了一個錯誤,如:來自`fs.readdir()`?的錯誤,則必須將這個錯誤作為第一個,也是唯一的參數傳遞給回調函數,并執行回調函數。
絕對不能直接在模塊文件中把結果打印到終端中,只能在原始程序文件中編寫打印結果的代碼。
當程序接收到一些錯誤的時候,請簡單的捕獲它們,并且在終端中打印出相關的信息
這里有四則規定,模塊必須遵守:
* 導出一個函數,這個函數能準確接收上述的參數。
* 當有錯誤發生,或者有數據的時候,準確調用回調函數。
* 不要改變其他的任何東西,比如全局變量或者 stdout。
* 處理所有可能發生的錯誤,并把它們傳遞給回調函數。
遵循一些約定的好處是,模塊可以被任何其他也遵守這些約定的人所使用。
## 提示
通過創建一個僅包含目錄讀取和文件過濾相關的函數的文件來建立一個新的模塊。要使模塊導出(export)單一函數(single function),可以將函數賦值給`module.exports`對象:
~~~
module.exports = function (args) { /* ... */ }
~~~
或者也可以使用命名函數,然后把函數名賦值給`module.exports`。
要在原來的程序中使用新的模塊,請用 require() 載入模塊,這和載入 fs 模塊時候用`require('fs')`一樣,唯一的區別在于本地模塊需要加上 ‘./‘ 這個相對路徑前綴。所以,如果模塊文件名字是 mymodule.js,那么需要像這樣寫:
~~~
var mymodule = require('./mymodule.js')
~~~
‘.js’ 這個文件擴展名通常是可以省略的。
現在,mymodule 這個變量就指向了模塊中 module.exports了,因為剛導出了一個單一的函數,所以現在所聲明的變量 mymodule 就是那個模塊所導出的函數了,就可以直接調用它了!
同樣,請記住,盡早捕獲錯誤,并且在回調中返回:
~~~
function bar (callback) {
foo(function (err, data) {
if (err)
return callback(err) // 盡早返回錯誤
// ... 沒有錯誤,處理 `data`
// 一切順利,傳遞 null 作為 callback 的第一個參數
callback(null, data)
})
}
~~~
## 代碼
### solution.js:
~~~
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)
})
})
~~~
### solution_filter.js:
~~~
var fs = require('fs')
var path = require('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)
})
}
~~~