node.js异步并行函数多次返回单个结果



我正在尝试使用node.js的异步模块并行上传几个文件。我的代码看起来像:

// fileArr is an array of objects. each object contains the attributes of the file to be uploaded - filename, path, destination path, etc.
// toUpload is an array to which i push all the functions i want to execute with async.parallel
  for (i=0; i<fileArr.length; i++) {
    var src = fileArr[i]['path']
    var dest = fileArr[i]['dest']
    var fn = function(cb) { self.upload(src, dest, headers, function(err, url) { 
      cb(null, url)   
    })  
  }
  toUpload.push(fn) 
  } // for loop ends here
async.parallel(toUpload, function(err, results) {
  console.log('results: ' + results)
}) 

我的问题是:对于n=toUpload中的函数数,results数组回调包含数组中最后一个并行任务的结果,n次。我想不通。似乎每个函数都应该用(null,url)向并行函数返回自己的回调。

此外,当我尝试使用src和dest的定义直接调用self.pload函数时:

self.upload(fileArr[i]['path'], fileArr[i]['dest'], headers, function(err, url) {
  cb(null, url)
})

我收到一个错误,说"无法读取未定义的属性'path'"。因此,fileArr[i]是未定义的。为什么会发生这种情况?我觉得任务和范围有点奇怪…

如果从问题(和代码)中看不出来,我对编程还很陌生。。

请记住,这本质上是:

var src, dest
for (i=0; i<fileArr.length; i++) {
  src = fileArr[i]['path']
  dest = fileArr[i]['dest']
  var fn = function(cb) {
    self.upload(src, dest, headers, function(err, url) { 
      cb(null, url)   
  })  
}

这可能会更清楚地表明,当调用fn函数时,for循环已经完成,因此srcdest将在每次调用fn时都有其最终循环值。

类似地,对于self.upload(fileArr[i]['path'], fileArr[i]['dest'], ...,在函数运行时,由于for循环已经完成,因此i === fileArr.length的值也会出现。

对此,最简单的解决方案是使用async.map

async.map(
  fileArr,
  function(file, callback){
    self.upload(file['src'], file['dest'], headers, function(err, url){
      callback(null, url);
    });
  },
  function(err, results) {
    console.log('results: ' + results)
  }
)

我将null作为错误传递,因为这就是您在示例中所做的,但您可能不应该丢弃错误,因为它们可能很重要。

最新更新