我正在为流星应用程序(Meteor 1.2.1)中使用的WYSIWYG编辑器编写上传插件。我使用Slingshot将文件上传到Amazon S3。上传文件后,我的插件会在编辑器中向上传的文件插入一个链接。到目前为止没什么好看的。
对于单个文件上传,这不是问题。如果是多文件上传,事情会变得更加困难。我想要的是,在上传所有文件之后,我最终会得到一个文件名和URL的数组,并插入一个包含所有链接的漂亮HTML列表(我不关心精确的文件/链接)序列)。
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个网址,我想我需要异步'发送' Slingshot的功能就像一个同步功能。
我希望我能正确理解Meteor.wrapAsync不会起作用,因为所有这些都是在客户端完成的。我查看了javascript Promise,但它相当压倒性。并且在Meteor环境中理解它变得更加困难。 Promise-thing看起来很有希望,但我不明白使用哪个包。
有人可以解释如何解决(客户端)连续运行多个(相同)异步函数的调用,收集结果并在完成所有上传后使用它们吗?
欣赏它,
CSPR
答案 0 :(得分:2)
async库有一个名为mapSeries
的方法,可以让您执行此操作。它允许您使用(可能的)异步函数迭代数组,并在最终异步任务完成时返回所有结果的数组:
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
方法并行运行任务。
答案 1 :(得分:1)
有没有什么能阻止你只是迭代输入文件,异步上传它们并询问我们是否已完成每次回调?
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!');
}