#!/usr/bin/env node
var fs = require('fs')
, async = require('async')
, program = require('commander')
program
.version('0.0.1')
.usage('<keywords>')
.parse(process.argv)
async.waterfall([
fs.readdir.bind(fs, __dirname),
parseHTML,
], saveResult)
function parseHTML(files, callback) {
var result = []
files.forEach(function(file) {
if (file.match(/\.html$/)) {
fs.readFile(file, 'utf8', function(err, data) {
if (err) throw err
result.push(data)
})
}
})
callback(null, result)
}
function saveResult(err, result) {
console.log(result)
}
我很困惑因为console.log(data)
确实输出了数据:
<p>File 1</p>
<p>File 2</p>
但最终的result
是一个空数组:[]
为什么我做错了?
答案 0 :(得分:1)
您必须等待查看结果,直到最后fs.readFile()
操作完成。这些是异步操作,它们将来会完成一些时间。您正在检查结果,然后才能完成。
有很多方法可以解决这个问题,但是这种方法可能会对您的代码造成最小的改变,因为它只是对已完成的代码进行了反击:
function parseHTML(files, callback) {
var result = [],
cntr = 0;
files.forEach(function(file) {
if (file.match(/\.html$/)) {
fs.readFile(file, 'utf8', function(err, data) {
if (err) throw err
result.push(data)
// see if we're done processing all the results
++cntr;
if (cntr === files.length) {
callback(null, result);
}
});
} else {
++cntr;
if (cntr === files.length) {
callback(null, result);
}
}
});
}
我个人更喜欢使用promises和Promise.all()
来解决这个问题。
这是一个使用Bluebird promise库的版本,它保留了你的一些其他结构:
var Promise = require("bluebird");
var fs = Promise.promisifyAll(require('fs'));
// your other code here
function parseHTML(files, callback) {
var promises = [];
files.forEach(function(file) {
if (file.match(/\.html$/)) {
promises.push(fs.readFileAsync(file, 'utf8'));
});
Promise.all(promises).then(function(results) {
// all results in results array
callback(null, results);
}, function(err) {
// error here
});
}
而且,这是一个完全承诺的版本:
var Promise = require("bluebird");
var fs = Promise.promisifyAll(require('fs'));
function parseHTML(files) {
var promises = [];
files.forEach(function(file) {
if (file.match(/\.html$/)) {
promises.push(fs.readFileAsync(file, 'utf8'));
});
return Promise.all(promises);
}
fs.readdirAsync(__dirname).then(parseHTML).then(function(results) {
// files are in the results array here
}).catch(function(err) {
// error here
});