如何根据promise做出asynchronous函数

问题是该function不会等待地图完成

我认为解决scheme是Promise.all但是我不知道如何使用这个function

exports.createProduct = (data) => { var imgS3arr = []; //array which we waiting for data.img.map((img, i) => { fetch.remote(img).then((base) => { var buf = Buffer.from(base[0], 'base64'); var imgS3 = { Key: data.title + i, //TODO: add random Body: buf, ContentEncoding: 'base64', ContentType: 'image/jpeg' }; s3Bucket.putObject(imgS3, function (err, data) { if (err) { console.log(err); console.log('Error uploading data: ', data); } else { var params = this.request.params; var region = this.request.httpRequest.region; imgS3arr.push('https://s3-' + region + '.amazonaws.com/' + params.Bucket + '/' + params.Key) } } ); }).catch((reason) => { }); }); //next part of code must be executed when all items pushed to 'imgS3arr' const product = new Product({ title: data.title, img: imgS3arr, //we waiting for this array }); return product.save((function (err) { if (err) { console.log(err); } else { console.log('Added new! \n' + product); } })); } 

有人能帮我解决这个问题吗?

你可以做这样的事情:

 // returns a promise that is resolved when everything is done // or rejected with the first error that occurs exports.createProduct = (data) => { var imgS3arr = []; //array which we waiting for return Promise.all(data.img.map((img, i) => { return fetch.remote(img).then((base) => { var buf = Buffer.from(base[0], 'base64'); var imgS3 = { Key: data.title + i, //TODO: add random Body: buf, ContentEncoding: 'base64', ContentType: 'image/jpeg' }; return s3Bucket.putObject(imgS3).promise().then(function(data) { // given other changes here and unfamiliarity with this code // I'm unsure if `this` still has the right value in it here var params = this.request.params; var region = this.request.httpRequest.region; imgS3arr.push('https://s3-' + region + '.amazonaws.com/' + params.Bucket + '/' + params.Key) }).catch(function(err) { // log error, then rethrow to keep the promise rejected console.log(err); console.log('Error uploading data: ', data); throw err; }); }); })).then(function() { const product = new Product({ title: data.title, img: imgS3arr, //we waiting for this array }); // use database interface that uses promises, not plain callbacks return product.save(...); } }); } 

对所作更改的总结和解释:

  1. data.img.map()内部,返回一个promise,以便.map()创build一个promise数组。
  2. 使用承诺数组上的Promise.all()来知道它们何时完成。
  3. 切换到s3Bucket.putObject(imgS3).promise()所以我们可以使用promises而不是普通的callback。
  4. logging之后在.catch()重新出现错误,所以promise保持拒绝
  5. 将代码放在Promise.all().then()处理程序中。
  6. product.save()切换到使用promise而不是普通callback的数据库接口,因此您可以直接链接该承诺(由于我们甚至不知道它是什么数据库,所以留给OP来做)。