nodejs:如何等待几个异步任务完成

时间:2016-04-15 15:52:48

标签: javascript node.js asynchronous

我有一个文件,我在写东西:

var stream = fs.createWriteStream("my_file.txt");
stream.once('open', function(fd) {
  names.forEach(function(name){
    doSomething(name);
  });
  stream.end();
});

这工作正常,我可以写入文件。 问题是doSomething()函数有一些异步的部分。可以使用dnsLookup函数给出一个示例。在我的doSomething()的某处,我有:

dns.lookup(domain, (err, addresses, family) => {
  if(err){
    stream.write("Error:", err);
  }else{
    stream.write(addresses);
  }
});

现在,我的问题是,由于DNS检查是异步的,代码会继续执行关闭流。当DNS响应最终到来时,它无法写入任何地方。 我已经尝试使用异步模块,但它不起作用。可能我做错了什么。

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

现在NodeJS大部分时间都在使用ES2015功能(我注意到你至少使用了一个箭头功能),你可以使用JavaScript中的原生承诺(之前你可以使用一个库):

var stream = fs.createWriteStream("my_file.txt");
stream.once('open', function(fd) {
  Promise.all(names.map(name => doSomething(name)))
  .then(() => {
    // success handling
    stream.end();
  })
  .catch(() => {
    // error handling
    stream.end();
  });
});

(如果您知道 Promise.all(names.map(name => doSomething(name)))忽略额外的参数并仅使用第一个参数,则行Promise.all(names.map(doSomething))可以只是doSomething

Promise.allspec | MDN)接受一个iterable,并返回一个在迭代中的所有promise都已解决时结算的promise(非promise值被视为已解析)承诺使用该值作为分辨率。)

doSomething变为:

function doSomething(name) {
  return new Promise((resolve, reject) => {
    dns.lookup(domain, (err, addresses, family) => {
      if(!err){                            // <== You meant `if (err)` here, right?
        stream.write("Error:", err);
        reject(/*...reason...*/);
      }else{
        stream.write(addresses);
        resolve(/*...possibly include addresses*/);
    });
  });
});

有各种各样的库将为你“承诺 - 如果”节点式回调,所以使用promises比上面的混合更少笨重;在这种情况下,您可以直接使用承诺dns.lookup的承诺,而不是创建自己的额外承诺。