如何用数组链接承诺

How to chain promises with arrays

问题:创建一个 AWS Lambda 函数以使用 Node 4.3 和 graphics magic 调整上传的 S3 图片的大小。

我的问题:我不知道如何将一组图片对象集成到承诺流程中。我能找到的所有堆栈示例都显示了在所有数据已知时承诺的对象数组。但是我需要先读取图像数据,然后将其传递给resize函数。

下面的函数在 resizePicture 解析之前完成。我知道问题不在于返回承诺并以正确的顺序解决。我被难住了。

var pictureSizes = [
  {width: 100, size: 'thumbnail', suffix: '_t'},
  {width: 300, size: 'small', suffix: '_s'},
  {width: 600, size: 'medium', suffix: '_m'},
  {width: 1000, size: 'large', suffix: '_l'}
];

exports.handler = function(event, context) {

  var srcBucket = event.Records[0].s3.bucket.name;.
  var srcKey = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "));
  var dstBucket = srcBucket + "pictures";
  var typeMatch = srcKey.match(/\.([^.]*)$/);
  var fileName = path.basename(srcKey);

  downloadImage({ Bucket: srcBucket, Key: srcKey})
  .then(result => pictureSizes.map(picture => resizePicture(result, picture)))
  .then(result => saveImage(result, dstBucket, fileName))
  .catch(err => console.log('error', err))
}

function downloadImage(params) {
  console.log('download Image', params);
  return new Promise(function(resolve, reject) {
    s3.getObject(params, function(err, data) {
      if (err) {
        reject(err);
      }
      resolve(data);
    })
  });
}

function resizePicture(result, picture) {
  return new Promise(function(resolve, reject) {
    const extension = result.ContentType.split('/')[1];
    gm(result.Body)
      .resize(picture.width)
      .toBuffer(extension, function(err, buffer) {
        if (err) {
          reject(err);
        } else {
          resolve({
            key: `${picture.suffix}.${extension}`,
            binary: buffer,
            ContentType: result.contentType
          })
        }
      });
  })
}

function saveImage(result, dstBucket, fileName) {
  return new Promise(function(resolve, reject) {
    s3.putObject({
      Bucket: dstBucket,
      Key: `${fileName}${result.key}`,
      Body: result.binary,
      ContentType: result.ContentType
    }, function(err, data) {
      if (err) {
        reject(err);
      }
      resolve(data);
    })
  })
}

啊,你快搞定了!您需要为此处生成的一系列承诺创建观察者:pictureSizes.map(picture => resizePicture(result, picture)).

试试 Bluebird's Promise.map,你的行可以读作:

.then(result => Promise.map(pictureSizes, picture => resizePicture(result, picture)))

如果你不想有任何嵌套函数,#bind 就是你想要的:

.then(result => Promise.map(pictureSizes, resizePicture.bind(null, result)))