node.js:使用async库在完成前两个时并行运行两个任务和最后一个任务



方案

需要并行运行两个任务,并完成firstTask && secondTask之后的第三个任务。一直在使用async库,并且代码有效,但是想知道我是否可以改进我的代码。

详细信息

任务1:readFileNames:读取文件夹并返回文件名。

任务2:copyFile:将config文件从SRC文件夹复制到目标文件夹。

任务3:writeConfig:将readFileNames的结果写入位于destination文件夹的config文件。

问题

我应该将parallel控制流与eachSync相结合吗?另外,想知道承诺是否会帮助我实现自己的目标?哪种方法在性能方面更好?异步与Q,或者我应该使用更抽象的库,例如orchestrator

以下是我到目前为止的工作,它有效,但想知道是否有更好的方法:

代码

var async = require("async");
var fs = require("fs-extra");
var dir = require("node-dir");
var path = require("path");
var _ = require("underscore");
var readFileNames = function (src, cb) {
  dir.files(src, function (err, files) {
    if (err) { return cb(err); }
    return cb(files);
  });
};
var copyFile = function (src, dest, cb) {
  fs.copy(src, dest, function (err) {
    if (err) { return cb(err); }
    return cb();
  });
};
var writeConfig = function (destFile, content, cb) {
  fs.appendFile(destFile, content, function (err) {
    if (err) { return cb(err); }
    return cb();
  });
};
var modulesFolder = path.join(__dirname, "modules");
var srcFile = path.join(__dirname, "src", "config.json");
var destFile = path.join(__dirname, "dest", "config.json");
async.parallel(
  [
    function (callback) {
      readFileNames(modulesFolder, function (files) {
        callback(null, files);
      });
    },
    function (callback) {
      copyFile(srcFile, destFile, function () {
        callback(null, "");
      });
    }
  ],
  // last callback
  function (err, results) {
    var toWrite = _.flatten(results);
    toWrite.forEach(function (content) {
      if(content) {
        writeConfig(destFile, content + "n", function () {
        });
      }
    });
    console.log("done");
  }
);

文件

├── dest
├── main.js
├── modules
│   ├── module1.txt
│   └── module2.txt
├── node_modules
│   ├── async
│   ├── fs-extra
│   └── node-dir
├── package.json
└── src
    └── config.json

我一直在使用异步库,并且代码有效,但是想知道我是否可以改进我的代码。

您正在使用太多匿名函数表达式。只需通过您要收到的callback即可!所有这些辅助功能(包括指定的功能)都是多余的。

另外,您的readFileNames功能不遵循节点回调约定。我认为您不打算将错误写入结果文件?

您的最终回调确实忽略了错误。

我应该将平行控制流与每个sync结合在一起?

我想你是说eachSeries,而不是eachSync?是的,如果您期望appendFile打电话给链条,那将是合理的。但是,您可以再次使用parallel,这将与您当前正在做的.forEach更紧密相关。但是,如果您应该使用async迭代方法,因为当前您还为时过早记录"done"

所以做

var async = require("async");
var fs = require("fs-extra");
var dir = require("node-dir");
var path = require("path");
var modulesFolder = path.join(__dirname, "modules");
var srcFile = path.join(__dirname, "src", "config.json");
var destFile = path.join(__dirname, "dest", "config.json");
async.parallel([
  function (callback) {
    dir.files(modulesFolder, callback);
  },
  function (callback) {
    fs.copy(srcFile, destFile, callback);
  }
], function(err, results) {
  if (err)
    return console.error(err);
  var toWrite = results[0] // ignore the result of the copy action
  async.eachSeries(toWrite, function(content, callback) {
    // if(content) not sure if needed at all
      fs.appendFile(destFile, content + "n", callback);
  }, function(err) {
    if (err)
      return console.error(err);
    console.log("done");
  });
});

另外,想知道承诺是否会帮助我实现自己想做的事情?

是的,他们也可以做到这一点,甚至可能更容易,更直接(如果您习惯了)。他们还可以简化错误处理。

哪种方法在性能方面更好?

都不。这个小脚本的性能受您系统的IO功能的限制,以及您的算法使用的并行程度。这两个库都可以实现。

您对async.parallel()的使用对我来说看起来不错,如果完成工作,就完成了。关于性能,您是否并行所有可以并行完成的任务?您的磁盘io速度有多快?这些问题比您选择的异步/保证图书馆的选择重要。

话虽如此,与异步相比,像Q这样的承诺库通常会稍微下降一点,因为它们往往会在没有严格必要的情况下执行process.nextTick,但是这种性能降级很小。在绝大多数情况下,绩效问题不应决定您选择异步/承诺库。

最新更新