Nodejs串联运行函数

所以现在我试图使用Nodejs来访问文件,以便将它们写入服务器并处理它们。

我已经把它分成以下几个步骤:

  • 遍历目录以生成所有文件path的数组
  • 将来自每个文件path的原始文本数据放在另一个数组中
  • 处理原始数据

前两个步骤工作正常,使用这些function:

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() 。 但是,使用callback似乎并不奏效。

 walk(rootdirectory, function(err, results) { if (err) throw err; filepaths = results.slice(); processfilepaths(processrawdata); }); 

这绝不会导致错误。 除了processrawdata()总是在processfilepaths()之前完成以外,一切看起来都是完美的。 我究竟做错了什么?

您在callback调用和asynchronous调用函数时遇到问题。 国际海事组织我会build议你使用一个库,如所有执行一个callback一旦所有的函数执行。

下面是一个例子,在这里函数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!"); } 

我认为对于你的问题,你可以使用Node.js的asynchronous模块:

 async.series([ function(){ ... }, function(){ ... } ]); 

为了回答你实际的问题,我需要解释Node.js是如何工作的:
比方说,当你调用一个asynchronous操作(比如说mysql数据库查询)时,Node.js发送“执行这个查询”给MySQL。 由于这个查询需要一些时间(可能是几毫秒),Node.js使用MySQLasynchronous库执行查询 – 返回到事件循环并在等待MySQL返回给我们时做其他事情。 就像处理那个HTTP请求一样。 所以,在你的情况下,这两个函数是独立的,并行执行。

了解更多信息:

  • 用于Node.js的Async.js
 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会asynchronous地调用每个读文件,它只设置事件和callback函数,然后当调用每个读文件的时候,它会执行if,在callback之前甚至有可能被调用。

您需要使用Promises或承诺模块(如async来序列化它。 你会做什么看起来像:

 async.XXXX(filepaths, processRawData, function (err, ...) { // function for when all are done if (callback) callback(); } ); 

其中XXXX是来自库,如series, parallel, each等等的function之一…你还需要知道的唯一的东西是在你的过程原始数据,asynchronous给你一个callback调用时完成。 除非你真的需要顺序访问(我不认为你这么做),为了尽可能多的排队,它应该执行得更快,也许只是稍微,但是它会更好地利用硬件。