javascript - 如何基于 Promise 制作异步函数

标签 javascript node.js es6-promise

问题是该函数不会等到 map 完成

我认为解决方案是 Promise.all 但我不知道如何使用这个功能

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() 创建一个 Promise 数组。
  2. 对该 Promise 数组使用 Promise.all() 来了解它们何时全部完成。
  3. 切换到 s3Bucket.putObject(imgS3).promise(),这样我们就可以使用 Promise 而不是普通的回调。
  4. 记录后在 .catch() 中重新抛出错误,因此 Promise 仍被拒绝
  5. 将要等待的代码放入 Promise.all().then() 处理程序中。
  6. product.save() 切换到使用 Promise 而不是普通回调的数据库接口(interface),这样您就可以直接链接该 Promise(留给 OP 来做,因为我们甚至不知道它是什么数据库)。

关于javascript - 如何基于 Promise 制作异步函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45887560/

相关文章:

javascript - 是否可以检测用户何时使用预测键盘打字?

node.js - 如何将sentry与node的kue一起使用?

javascript - 为什么等待一个空的 JavaScript Promise 不能让运行时保持事件状态?

javascript regexp 两个字符都是可选的,但只有一个字符无效

javascript - {jpm} 如何将任何页面替换为自己的?

javascript - 对 js 文件中的 html 内容执行 javascript

ruby-on-rails - Assets :precompile with uglify fails

node.js - 导出 NODE_ENV=生产不会更改 gulpfile.js 中的 process.env.NODE_ENV

javascript - Promises.all 的快速失败行为

javascript - 在迭代到循环的下一次迭代之前完成 FOR 循环内的所有函数