JS Promise 等待嵌套的异步函数

时间:2021-03-29 22:00:44

标签: javascript promise

我在正确计时 2 个异步操作时遇到问题,因此外部函数在继续之前等待内部函数完成。我正在尝试实施的解决方案基于使用 ES2015 的现有解决方案,因此我无法使用 await 而必须使用 Promises。

该解决方案分为多个类,为了便于概述,我将其称为 Main、Invoker 和 Inner。所以 Main 类使用 Invoker 的一个实例异步执行来自 Inner 类的命令,然后应该等待响应,这有效但它不等待来自 setSize() 的异步 Image.onload()内部类。

class Inner extends Component{
    setSize(size){
        const newImage = { url: null, imageName: canvasImage.imageName};
        
        ... some stuff...
        const tempImage = new Image();
        tempImage.src = canvas.toDataURL();
        tempImage.onload = function(){
        
            ... some stuff...
            const tempCanvas = document.createElement("canvas");
            const tempCtx = tempCanvas.getContext("2d");
            tempCtx.drawImage(image, x, y, xa, ya);

            newImage.url = tempCanvas.toDataURL();
        }
        return Promise.resolve(newImage);
    }
}


class Main{
    resize(size){
        imageData = this.execute(commandName,'setSize', size);
        
        imageData.then(image => {
            ... do stuff with image data...
        });
    }
    execute(commandName, ...args) {
        return this._invoker.execute(commandName, ...args);
    }
}

class Invoker{
    execute(...args) {

        let [command] = args;
        if (isString(command)) {
          command = commandFactory.create(...args);
        }

        return this._invokeExecution(command).then((value) => {
          this.clearRedoStack();

          return value;
        });
    }
}

我已经尝试在 onload 函数内的 setSize 函数中移动“return Promise.resolve(newImage)”,但随后我在调用程序中遇到错误,因为缺少解析。 有什么想法吗?

2 个答案:

答案 0 :(得分:3)

你需要返回一个 promise 并在 onload 中解决它。

setSize () {
  return new Promise((resolve, reject) => {
    ...
    tempImage.onload = function () {
      ...
      resolve(newimage)
    }
  })
}

答案 1 :(得分:3)

由于 setSize 函数使用基于回调的语法和 onload,您需要等到 onload 函数被浏览器调用,

您可以从 setSize 返回一个 promise 并处理 onloadresolveonerrorreject,例如:

setSize(size){
    return new Promise((res, rej) => {
      const newImage = { url: null, imageName: canvasImage.imageName};
      
      ... some stuff...
      const tempImage = new Image();
      tempImage.src = canvas.toDataURL();
      tempImage.onload = function(){
      
          ... some stuff...
          const tempCanvas = document.createElement("canvas");
          const tempCtx = tempCanvas.getContext("2d");
          tempCtx.drawImage(image, x, y, xa, ya);

          newImage.url = tempCanvas.toDataURL();
          res(newImage);
      }
      tempImage.onerror = function(error) {
        rej(error)
      }
    })
}