以同步方式执行asynchronous调用

在过去的几个小时里,我一直试图绕过这个问题,但无法弄清楚。 我想我还是必须习惯于函数式的编程风格;)

我写了一个遍历目录结构的recursion函数,并对某些文件进行处理。 这个函数使用asynchronousIO方法。 现在我想在整个遍历完成时执行一些操作。

我如何确保在所有parse调用完成后执行此操作,但仍使用asynchronousIOfunction?

 var fs = require('fs'), path = require('path'); function parse(dir) { fs.readdir(dir, function (err, files) { if (err) { console.error(err); } else { // f = filename, p = path var each = function (f, p) { return function (err, stats) { if (err) { console.error(err); } else { if (stats.isDirectory()) { parse(p); } else if (stats.isFile()) { // do some stuff } } }; }; var i; for (i = 0; i < files.length; i++) { var f = files[i]; var p = path.join(dir, f); fs.stat(p, each(f, p)); } } }); } parse('.'); // do some stuff here when async parse completely finished 

寻找Step模块 。 它可以链接asynchronous函数调用,并将结果从一个传递到另一个。

你可以使用asynchronous模块。 它的自动function非常棒。 如果你有函数A()和函数B()和函数C()。 函数B()和C()都依赖于使用从函数A()返回的值的函数A()。 使用asynchronous模块function,您可以确保函数B和C只有在函数A执行完成时才会执行。

参考: https : //github.com/caolan/async

 async.auto({ A: functionA(){//code here }, B: ['A',functionB(){//code here }], C: ['A',functionC(){//code here }], D: [ 'B','C',functionD(){//code here }] }, function (err, results) { //results is an array that contains the results of all the function defined and executed by async module // if there is an error executing any of the function defined in the async then error will be sent to err and as soon as err will be produced execution of other function will be terminated } }) }); 

在上面的例子中,函数B和函数C一起执行一次函数执行就会完成。 因此,functionB和functionC将被同时执行

 functionB: ['A',functionB(){//code here }] 

在上面的行中,我们使用'A'

而functionD只有在functionB和functionC执行完成时才会执行。

如果在任何函数中都会有错误,那么其他函数的执行将被终止,下面的函数将被执行。在那里你可以写出你的成功和失败的逻辑。

 function (err, results) {} 

所有函数“results”的成功执行将包含async.auto中定义的所有函数的结果

 function (err, results) {} 

看看你的原始代码的修改,而不需要asynchronous帮助程序库。

 var fs = require('fs'), path = require('path'); function do_stuff(name, cb) { console.log(name); cb(); } function parse(dir, cb) { fs.readdir(dir, function (err, files) { if (err) { cb(err); } else { // cb_n creates a closure // which counts its invocations and calls callback on nth var n = files.length; var cb_n = function(callback) { return function() { --n || callback(); } } // inside 'each' we have exactly n cb_n(cb) calls // when all files and dirs on current level are proccessed, // parent cb is called // f = filename, p = path var each = function (f, p) { return function (err, stats) { if (err) { cb(err); } else { if (stats.isDirectory()) { parse(p, cb_n(cb)); } else if (stats.isFile()) { do_stuff(p+f, cb_n(cb)); // if do_stuff does not have async // calls inself it might be easier // to replace line above with // do_stuff(p+f); cb_n(cb)(); } } }; }; var i; for (i = 0; i < files.length; i++) { var f = files[i]; var p = path.join(dir, f); fs.stat(p, each(f, p)); } } }); } parse('.', function() { // do some stuff here when async parse completely finished console.log('done!!!'); }); 

像这样的东西可以工作 – 对你的代码的基本改变是循环变成了一个recursion调用,直到完成后才消耗一个列表。 这样可以添加一个外部callback函数(在parsing完成后可以进行一些处理)。

 var fs = require('fs'), path = require('path'); function parse(dir, cb) { fs.readdir(dir, function (err, files) { if (err) cb(err); else handleFiles(dir, files, cb); }); } function handleFiles(dir, files, cb){ var file = files.shift(); if (file){ var p = path.join(dir, file); fs.stat(p, function(err, stats){ if (err) cb(err); else{ if (stats.isDirectory()) parse(p, function(err){ if (err) cb(err); else handleFiles(dir, files, cb); }); else if (stats.isFile()){ console.log(p); handleFiles(dir, files, cb); } } }) } else { cb(); } } parse('.', function(err){ if (err) console.error(err); else { console.log('do something else'); } }); 

看下面的解决scheme,它使用延迟模块:

 var fs = require('fs') , join = require('path').join , promisify = require('deferred').promisify , readdir = promisify(fs.readdir), stat = promisify(fs.stat); function parse (dir) { return readdir(dir).map(function (f) { return stat(join(dir, f))(function (stats) { if (stats.isDirectory()) { return parse(dir); } else { // do some stuff } }); }); }; parse('.').done(function (result) { // do some stuff here when async parse completely finished }); 

我一直在使用syncrhonize.js ,取得了巨大的成功。 甚至还有一个挂起的请求(工作得很好)来支持具有多个参数的asynchronous函数。 比节点同步imho更好,更容易使用。 增加了奖励,它有易于理解和详尽的文档,而节点同步不。

支持两种不同的方法来连接同步,一个有争议的/等待模式(就像@Mariusz Nowak所build议的那样)和一个更细的函数目标方法。 文档是相当简单的每个。

build议使用node-seq https://github.com/substack/node-seq

由npm安装。

我正在使用它,我喜欢它。

查找节点同步 ,这是一个简单的库,允许您以同步方式调用任何asynchronous函数。 主要的好处是,它使用JavaScript本地devise – Function.prototype.sync函数,而不是沉重的API,你需要学习。 另外,通过node-sync同步调用的asynchronous函数并不会阻塞整个进程 – 它只阻塞当前线程!