【问题标题】:Waiting for Promise- Angular 2等待承诺 - Angular 2
【发布时间】:2016-07-15 19:19:41
【问题描述】:

我正在使用 Angular2 构建一个应用程序。我正在尝试将分段上传到 Amazon S3。我需要根据成功上传/失败的对象显示“成功”或“失败”烤面包机。我的代码中有“承诺”。但是,即使在承诺完成之前,成功的烤面包机也会显示出来。我不确定这里出了什么问题。有人可以在这里帮助我吗?

这是来电者:

this.multipartupload(params).then((data) => {

          var fileNameArr = params.Key.split('/')
          this.uiService.showMessage('success', fileNameArr[fileNameArr.length - 1] + ' Uploaded');

      }).catch((err) => {
        this.uiService.showMessage('warning', err.message);
      })

分段上传分为三个不同的阶段:创建、上传和完成。我只想在“完成”阶段完成后显示成功消息。下面是上面代码调用的'multipartUpload'的代码:

multipartupload(params: any){
      var s3 = this.getS3();
      var multipartParams = {
        Bucket: params.Bucket,
        Key: params.Key,
        ServerSideEncryption: params.ServerSideEncryption
      }

      var partSize = 5 * 1024 * 1024;
      var partNum = 0;
      var multipartMap = {
        Parts: []
      };
      var numPartsLeft = Math.ceil(params.Body.size / partSize);
      return s3.createMultipartUpload(multipartParams).promise()
        .then((data) => {
          for(var rangeStart = 0; rangeStart < params.Body.size; rangeStart += partSize){
            var end = Math.min(rangeStart + partSize, params.Body.size);
            partNum++;
            var partParams = {
              Body: params.Body.slice(rangeStart, end),
              Bucket: params.Bucket,
              Key: params.Key,
              PartNumber: String(partNum),
              UploadId: data.UploadId
            }
            return uploadPart(s3, data, partParams); // -> the toastr is shown at this point. I want it to wait till all the parts are uploaded.
          }
        })
      .catch((err) => {
        return err;
      })

      function uploadPart(s3, multipart, partParams, tryNum = 0){
        var tryNum = tryNum | 1;
        s3.uploadPart(partParams).promise()
          .then(
            (mData) => {
              multipartMap.Parts[partParams.PartNumber - 1] = {
                ETag: mData.ETag,
                PartNumber: Number(partParams.PartNumber)
              };
            if (--numPartsLeft > 0) return;
            var doneParams = {
              Bucket: params.Bucket,
              Key: params.Key,
              MultipartUpload: multipartMap,
              UploadId: multipart.UploadId
            };
            return s3.completeMultipartUpload(doneParams).promise().then((data) =>{
              return data;
            })
            .catch((err) => {
              return err;
            })
          })
        .catch((multiErr) => {
            if(tryNum < 3){
              uploadPart(s3, multipart, partParams, tryNum + 1);
            }
            return multiErr;
          })
      }
    }

我知道这段代码有点长。但我想传达整个背景。感谢您的理解。如果有人可以分享如何等待最后一部分成功上传,我将不胜感激。

【问题讨论】:

  • 两个问题:(1)params.Body.size是params.Body.length的同义词吗? (2)var tryNum = tryNum | 1;能解释一下吗?
  • 1) params.Body.size 是 params.Body.length 的同义词。我应该到处使用 params.Body.size 。我将编辑代码。 2)哦,是的!我可以将 tryNum 的默认值设置为 1,而不是 tryNum = tryNum | 1

标签: javascript amazon-web-services asynchronous angular promise


【解决方案1】:

看来你不见了:

  • for 循环中生成的 Promise 聚合
  • 几个回报

这里有一些额外的整理...

this.multipartupload(params)
.then((data) => {
    var fileNameArr = params.Key.split('/');
    this.uiService.showMessage('success', fileNameArr[fileNameArr.length - 1] + ' Uploaded');
}).catch((err) => {
    this.uiService.showMessage('warning', err.message);
});

multipartupload(params: any) {
    var s3 = this.getS3(),
        partSize = 5 * 1024 * 1024,
        partNum = 0,
        multipartMap = { Parts: [] };
    var numPartsLeft = Math.ceil(params.Body.length / partSize);
    return s3.createMultipartUpload({
        Bucket: params.Bucket,
        Key: params.Key,
        ServerSideEncryption: params.ServerSideEncryption
    }).promise()
    .then((data) => {
        var promises = []; // <<<<<<< create an array of promises
        for(var rangeStart = 0; rangeStart < params.Body.length; rangeStart += partSize) {
            promises.push(uploadPart(s3, data, {
                Body: params.Body.slice(rangeStart, Math.min(rangeStart + partSize, params.Body.length)),
                Bucket: params.Bucket,
                Key: params.Key,
                PartNumber: String(++partNum),
                UploadId: data.UploadId
            }, 1));
        }
        return Promise.all(promises) // <<<<<<< return a single aggregated promise.
        .then((results => results.filter(res => res !== null))); // filter out any nulls delivered by the (--numPartsLeft > 0) condition below.
    });

    function uploadPart(s3, multipart, partParams, tryNum) {
        return s3.uploadPart(partParams).promise()
    //  ^^^^^^
        .then((mData) => {
            multipartMap.Parts[partParams.PartNumber - 1] = {
                ETag: mData.ETag,
                PartNumber: Number(partParams.PartNumber)
            };
            if (--numPartsLeft > 0) {
                return null;
            }
            return s3.completeMultipartUpload({
                Bucket: params.Bucket,
                Key: params.Key,
                MultipartUpload: multipartMap,
                UploadId: multipart.UploadId
            }).promise();
        }).catch((multiErr) => (tryNum < 3) ? uploadPart(s3, multipart, partParams, tryNum + 1) : multiErr); // note the implicit return here.
    }
}

【讨论】:

  • 我想知道这部分。我从来不知道这样的 Promise 聚合是可能的。非常感谢。让我看看。
  • 我使用了原生 ES6(和 Bluebird)语法 Promise.all()。当你在 Angular 中时,你可能需要$q.all()。
猜你喜欢
  • 2018-01-17
  • 2017-04-04
  • 2017-07-31
  • 2018-05-29
  • 1970-01-01
  • 2013-09-16
  • 2019-04-29
  • 2020-10-31
  • 2019-12-10
相关资源
最近更新 更多