【问题标题】:How to use a promise in do-while loop waiting a callback to be completed如何在do-while循环中使用承诺等待回调完成
【发布时间】:2019-05-06 13:37:10
【问题描述】:

我有一个回调,它等待来自 HTTP 请求的响应,如果文件成功上传,该请求会以“完成”一词进行响应,并且我通过回调发出一个请求以每次上传单个文件。

我想要的是,当响应“完成”时,我想用do-while 循环上传多个文件,我正在考虑用 Promise 来做到这一点,但我真的不知道怎么做。

我现在的代码:

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);
  })();
}

【问题讨论】:

  • 你在哪里传递回调?
  • 顺便说一句,self 是不必要的。 this只能在不同的功能之间有所不同。
  • 你标记为my callback的部分实际上并不是一个回调函数。
  • @Andy 是的,它是一个数组。
  • @Adam 当然。虽然它简化了同步流控制的使用,就像 OP 希望使用的那样。

标签: javascript promise salesforce-lightning


【解决方案1】:

您必须使您的 uploadHelper 方法不是 aync 才能实现您想要的。 尝试使用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

【讨论】:

    【解决方案2】:

    当您的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, /*...*/);
      }
    

    现在我们有了它,我们可以在 async 函数中简单地 await 那个承诺:

     (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);
        }
      })();
    

    【讨论】:

      【解决方案3】:

      摆脱while 循环,每次使用它时只需将popfileInput 数组中删除一个项目。当数组为空时取消一切。

      (不过你需要有一个有效的回调函数......)

      【讨论】:

      • 什么?这与问题有什么关系?他还可以使用 for 循环...或...
      • 在承诺/回调情况下使用任何类型的“经典”循环有点不寻常!
      【解决方案4】:

      您可以使用自动运行功能来做到这一点:

                  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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-09-09
        • 1970-01-01
        • 2015-11-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-04-25
        相关资源
        最近更新 更多