所以现在我尝试使用Nodej来访问文件,以便将它们写入服务器并进行处理。
我已将其拆分为以下步骤:
前两个步骤正常,使用这些功能:
var walk = function(dir, done) {
var results = [];
fs.readdir(dir, function(err, list) {
if (err) return done(err);
var pending = list.length;
if (!pending) return done(null, results);
list.forEach(function(file) {
file = path.resolve(dir, file);
fs.stat(file, function(err, stat) {
if (stat && stat.isDirectory()) {
walk(file, function(err, res) {
results = results.concat(res);
if (!--pending) done(null, results);
});
} else {
results.push(file);
if (!--pending) done(null, results);
}
});
});
});
};
function processfilepaths(callback) {
// reading each file
for (var k in filepaths) { if (arrayHasOwnIndex(filepaths, k)) {
fs.readFile(filepaths[k], function (err, data) {
if (err) throw err;
rawdata[k] = data.toString().split(/ *[\t\r\n\v\f]+/g);
for (var j in rawdata[k]) { if (arrayHasOwnIndex(rawdata[k], j)) {
rawdata[k][j] = rawdata[k][j].split(/: *|: +/);
}}
});
}}
if (callback) callback();
}
显然,我想在加载完所有数据后调用函数processrawdata()
。但是,使用回调似乎不起作用。
walk(rootdirectory, function(err, results) {
if (err) throw err;
filepaths = results.slice();
processfilepaths(processrawdata);
});
这绝不会导致错误。除了processrawdata()
总是在processfilepaths()
之前完成之外,一切似乎都运行得很好。我做错了什么?
答案 0 :(得分:1)
我认为对于您的问题,您可以将async模块用于Node.js:
async.series([
function(){ ... },
function(){ ... }
]);
<小时/> 为了回答你的实际问题,我需要解释Node.js的工作原理:
了解更多信息:
答案 1 :(得分:1)
您遇到回调调用和异步调用函数的问题。 IMO我建议您在执行所有函数后使用after-all等库来执行回调。
以下是一个例子,一旦调用了包含done
的所有函数,就会调用函数next
。
var afterAll = require('after-all');
// Call `done` once all the functions
// wrapped with next() get called
next = afterAll(done);
// first execute this
setTimeout(next(function() {
console.log('Step two.');
}), 500);
// then this
setTimeout(next(function() {
console.log('Step one.');
}), 100);
function done() {
console.log("Yay we're done!");
}
答案 2 :(得分:0)
function processfilepaths(callback) {
// reading each file
for (var k in filepaths) { if (arrayHasOwnIndex(filepaths, k)) {
fs.readFile(filepaths[k], function (err, data) {
if (err) throw err;
rawdata[k] = data.toString().split(/ *[\t\r\n\v\f]+/g);
for (var j in rawdata[k]) { if (arrayHasOwnIndex(rawdata[k], j)) {
rawdata[k][j] = rawdata[k][j].split(/: *|: +/);
}}
});
}}
if (callback) callback();
}
意识到你有:
for
readfile (err, callback) {... }
if ...
Node将异步调用每个readfile,它只设置事件和回调,然后当它完成调用每个readfile时,它将执行if,之后回调可能甚至有机会被调用。
您需要使用Promises或像async
这样的承诺模块来序列化它。你会做什么看起来像:
async.XXXX(filepaths, processRawData,
function (err, ...) {
// function for when all are done
if (callback) callback();
}
);
其中XXXX
是库中的函数之一,如series, parallel, each
等...您还需要知道的唯一事情就是在您的进程中原始数据,async会给您一个回调函数完成后。除非你真的需要顺序访问(我不认为你这样做),否则使用parallel可以排队尽可能多的i / o事件,它应该执行得更快,可能只是稍微一点,但它会更好利用硬件。