等待Promise-Angular 2

时间:2016-07-13 22:22:20

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

我正在使用Angular2构建应用程序。我正在尝试将Multipart上传到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 个答案:

答案 0 :(得分:1)

看起来你错过了:

  • for循环
  • 中生成的承诺汇总
  • 几个回报

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

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.
    }
}