如何根据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(...); } }); }
对所作更改的总结和解释:
- 在
data.img.map()
内部,返回一个promise,以便.map()
创build一个promise数组。 - 使用承诺数组上的
Promise.all()
来知道它们何时完成。 - 切换到
s3Bucket.putObject(imgS3).promise()
所以我们可以使用promises而不是普通的callback。 - logging之后在
.catch()
重新出现错误,所以promise保持拒绝 - 将代码放在
Promise.all().then()
处理程序中。 - 将
product.save()
切换到使用promise而不是普通callback的数据库接口,因此您可以直接链接该承诺(由于我们甚至不知道它是什么数据库,所以留给OP来做)。