处理多个上传的文件 'synchroneously'

Handling multiple uploaded files 'synchroneously'

我正在为我在 Meteor 应用程序 (Meteor 1.2.1) 中使用的 WYSIWYG 编辑器编写上传插件。我使用 Slingshot 将文件上传到 Amazon S3。上传文件后,我的插件会在编辑器中向上传的文件插入一个 link 。到目前为止没有什么特别的。

对于单个文件上传,这不是问题。如果是多文件上传,事情会变得更难。我想要的是,在所有文件上传后,我将得到一个文件名数组和 URLS,并插入一个包含所有 links 的漂亮 HTML-列表(我不关心精确的 file/link 序列)。

Slingshot 使用异步函数上传文件:

uploader.send(document.getElementById('input').files[0], function (error, downloadUrl) {
  if (error) {
    // Log service detailed response.
    console.error('Error uploading', uploader.xhr.response);
    alert (error);
  } else {
    Meteor.users.update(Meteor.userId(), {$push: {"profile.files": downloadUrl}});
  }
});

回调中返回上传文件的URL。例如,为了从 5 个上传的文件中收集 5 个 url,我想我需要 Slingshot 的异步 'send' 函数来表现得像一个同步函数。

我希望我理解正确,Meteor.wrapAsync 不会工作,因为所有操作都在客户端完成。我调查了 javascript Promise,但它相当令人难以抗拒。在 Meteor 上下文中理解它变得更加困难。 Promise-thing 看起来很有前途,但我不知道该使用哪个包。

有人可以解释如何处理(客户端)运行 连续多次(相同)调用异步函数,收集结果并在所有上传完成后使用它们吗?

欣赏,

Cspr

是否有什么阻止您迭代输入文件、异步上传它们并询问我们是否已完成每个回调?

var inputs = document.getElementsByTagName('input');
var urls = [];

for (var i = 0; i < inputs.length; i++) {

  if (inputs[i].files == null) { continue; }

  uploader.send(inputs[i].files[0], function (error, downloadUrl) {

    if (error) {

      console.error('Error uploading', uploader.xhr.response);

    } else {

      urls.push(downloadUrl);

      if (urls.length > inputs.length - 1)
        allFilesUploaded();
    }
  });
}

function allFilesUploaded () {

  Meteor.users.update(Meteor.userId(), {$push: {"profile.files": urls}});
  console.log('All done!');

}

async 库有一个名为 mapSeries 的方法,可让您执行此操作。它允许您使用(可能)异步函数遍历数组,并在最终异步任务完成时 return 一个包含所有结果的数组:

var files = [file1, file2, file3];

function iterator(file, callback) {
  uploader.send(file, function(err, downloadUrl) {
    if (err) callback(err);
    else callback(null, downloadUrl);
  });
}

function done(err, results) {
  // results is an array of URLs
}

async.mapSeries(files, iterator, done);

如果您不关心请求的处理顺序,可以使用常规 async.map 方法并行 运行 任务。