如何在do-while循环中使用Promise等待回调完成

时间:2019-05-06 13:37:11

标签: javascript promise salesforce-lightning

我有一个回调,它等待HTTP请求的响应,如果文件成功上传,该响应将用单词“ done”响应,并且我通过回调发出一个请求,每次都上传一个文件。

我想要的是,当响应“完成”时,我想使用do-while循环上传多个文件,并且我正在考虑使用promises进行操作,但是我真的不知道如何做。

现在我的代码:

var self = this;

let i = 0;
let fileInput = fileCmp.get("v.files");

do {

  // my callback
  self.uploadHelper(component, event, fileInput[i]);
  console.log("Uploading: " + fileInput[i].name);
  i++;

} while (i < fileInput.length);

我想要做的是仅当我收到响应“完成”或呼叫中的其他内容时转到i=1(第二个文件)。

uploadHelper()调用的我的回调:

uploadChunk: function (component, file, fileContents, fromPos, toPos, attachId) {

  console.log('uploadChunk');
  var action = component.get("c.saveTheChunk");
  var chunk = fileContents.substring(fromPos, toPos);

  action.setParams({
    parentId: component.get("v.recordId"),
    fileName: file.name,
    base64Data: encodeURIComponent(chunk),
    contentType: file.type,
    fileId: attachId
  });

  action.setCallback(this, function (a) {

    console.log('uploadChunk: Callback');
    attachId = a.getReturnValue();

    fromPos = toPos;
    toPos = Math.min(fileContents.length, fromPos + this.CHUNK_SIZE);

    if (fromPos < toPos) {
      this.uploadChunk(component, file, fileContents, fromPos, toPos, attachId);
    } else {
      console.log('uploadChunk: done');
      component.set("v.showLoadingSpinner", false);
      // enabling the next button
      component.set("v.nextDisabled", false);
      component.set("v.uploadDisabled", true);
      component.set("v.clearDisabled", true);
      component.set("v.showToast", true);
      component.set("v.toastType", 'success');
      component.set("v.fileName", '');
      component.set("v.toastMessage", 'Upload Successful.');
    }
  });

  $A.getCallback(function () {
    $A.enqueueAction(action);
  })();
}

4 个答案:

答案 0 :(得分:0)

您必须使自己的uploadHelper方法不具有异步性才能实现所需的功能。 尝试使用asyncawaitPromise对象在函数中创建一个Promis(而不是回调),并强制其同步发生。

可能看起来像这样:

// uploadHelper definiton, fit its to your code
const uploadHelper = (component, event, file) => {

    // Create the promise
    return new Promise(function(component, event, file) {
        // Do what you want to do
    })
}

// Use it
var self = this;
let i = 0;
let fileInput = fileCmp.get("v.files");
do{
    await self.uploadHelper(component, event, fileInput[i]).then(function() {
        console.log("Uploading: "+fileInput[i].name);
        i++;
    });
}
while(i< fileInput.length);

有关更多信息,请尝试以下链接: https://developer.mozilla.org/he/docs/Web/JavaScript/Reference/Global_Objects/Promise https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

答案 1 :(得分:0)

当您的uploadChunk执行异步任务时,该函数采取回调是有意义的,当任务完成时该回调将被回调(您的代码尚不包含任何回调)。由于回调难以处理(尤其是使用循环),因此将回调包装成Promise(在调用回调时解决)是很有意义的:

  uploadChunk: function (component, file, fileContents, fromPos, toPos, attachId) {
    return new Promise(resolve => { // the promise gets returned immeadiately, the "resolve" callback can be called to resolve it
      // ....
      action.setCallback(this, function (a) {
        //...
        resolve();
      });
    });
  },

您的uploadHelper现在可以将返回的承诺返回到循环中:

  uploadHelper(component, event, file) {
    //...
    return this.uploadChunk(component, file, /*...*/);
  }

现在我们有了这个,我们可以简单地awaitasync函数内部承诺:

 (async () => { // arrow function to preserve "this"
    for(const file of files) { // Why do...while if you can use a for..of?
      await this.uploadChunk(component, event, file);
    }
  })();

答案 2 :(得分:-1)

摆脱while循环,并在每次使用pop数组时只需fileInput即可。当数组为空时,取消所有操作。

(尽管您需要拥有一个有效的回调函数...)

答案 3 :(得分:-1)

嘿,您可以使用自动运行功能:

            var self = this;
            let i = 0;
            let fileInput = fileCmp.get("v.files");
            do{
                // my callback
                (()=>{
                   self.uploadHelper(component, event, fileInput[i]);
                   console.log("Uploading: "+fileInput[i].name);
                   i++;
                })();
            }
            while(i< fileInput.length);