如何使用nodejs编写异步程序?

时间:2016-09-12 06:16:47

标签: node.js asynchronous callback

让我们说,例如,我想写一个nodejs程序,其中我有两个或三个独立的部分,如fs.readdir,fs.copy等在不同的位置,但结果所有三个动作将被发送到像这样的json文件:

var fs = require('fs-extra');

var jsd = {
    "act1" : false,
    "act2" : false,
    "act3" : false
}

fs.readdir(path1, function (err, files) {
    if (err)  jsd.act1 = err;
    for (x in files)  console.log(files[x]);
    jsd.act1 = true;
});

fs.copy(path2, path3, function (err) {
    if (err)  jsd.act2 = err;
    jsd.act2 = true;
});

fs.remove(path4, function (err) {
    if (err)  jsd.act3 = err;
    jsd.act3 = true;
});

// all three of the above actions are independent, so it makes sense that all of them are executed asynchronously.
// Now we write jsd object to a json file; jsd's contents are dependent on the above actions though

fs.writeJson("./data.json", jsd, function (err, files) {
    if (err)   return console.error(err);
});

如何确保将正确的数据输入到 data.json 文件中,即fs.writeJson在首先执行之前的操作后执行?

我知道有一种方法可以嵌套所有这些,即

readdir() {
  copy() {
    remove() {
      writeJson();
    }
  }
}

但这可能导致回调地狱,那么有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

你可以使用Promise或模块异步, 如果您使用promise,首先必须将所有回调函数转换为Promise,如下所示:

const reddir = function(path) {
  return new Promise((resolve, reject) => {
    fs.readdir(path, (err, files) => {
      if (err) return reject(err);
      for (x in files)  console.log(files[x]);
      resolve(true);
    });
  })  
}
然后你可以使用

Promise.all([reddir(path1), copy(path2, path3), remove(path4)])
  .spread((act1, act2, act3) => { //.spread is bluebird feature
    return writeJson(./data.json);
  })
  .catch(e => {
    // all error can handled in this
  })

如果使用异步模块,可以像这样写:

async.parallel({
  act1: function(cb){
    fs.reddir(path1, (err, files) => {
      if (err) return cb(err);
      for (x in files)  console.log(files[x]);
      cb(true);
    })
  },
  act2: ...
},(err, jsd) => { // jsd will be {act1: true, act2: ...}
  if (err) return console.error(err); // handle all above error here;
  fs.writeJson("./data.json", jsd, function (err, files) {
    if (err)   return console.error(err);
  });
})