【问题标题】:Capture result of HTML5 FileReader when using promises in async在异步中使用 Promise 时捕获 HTML5 FileReader 的结果
【发布时间】:2019-04-12 03:48:00
【问题描述】:

我有一个 Angular 4 应用程序,我正在读取图像并尝试将 base64 字符串传递给另一个变量 - 但是由于它的异步性质,我遇到了问题 - image.src 是空的,因此值是否已正确传递给图像对象?

ngAfterViewInit(): void {
    let image = new Image();
    var promise = this.getBase64(fileObject, this.processImage());
    promise.then(function(base64) {
        console.log(base64);    // outputs string e.g 'data:image/jpeg;base64,........'
    });

    image.src = base64; // how to get base64 string into image.src var here??

    let editor = new PhotoEditorSDK.UI.ReactUI({
        container: this.editor.nativeElement
        editor: {
           image: image
        }
    });
}

/**
 * get base64 string from supplied file object
 */
public getBase64(file, onLoadCallback) {
    return new Promise(function(resolve, reject) {
        var reader = new FileReader();
        reader.onload = function() { resolve(reader.result); };
        reader.onerror = reject;
        reader.readAsDataURL(file);
    });
}

public processImage() {

}

【问题讨论】:

  • 为什么不把let image = new Image();image.src = base64;放在promise回调函数里面?
  • 将其移至promise.then 或使用异步等待? +400 有什么问题???
  • 所以你想使用 Promise 但不想等待它被实现。

标签: angular html typescript es6-promise photoeditorsdk


【解决方案1】:

由于getBase64 是异步操作,因此您不能立即使用它的结果。您需要通过调用then(您已经尝试过)或使用async/await 来等待它。

async/await 版本(也是 es 2017 标准的一部分)更易于理解,特别是如果您不熟悉异步编程。一般的经验法则,如果您看到 Promise 并需要使用该值,您将需要使用 await 运算符(并使您的方法异步)

async ngAfterViewInit() {
    let image = new Image();
    var base64 = await this.getBase64(fileObject, this.processImage());

    image.src = base64; //Now available

    let editor = new PhotoEditorSDK.UI.ReactUI({
        container: this.editor.nativeElement
        editor: {
           image: image
        }
    });
}
public getBase64(file, onLoadCallback) {
    return new Promise<string>(function(resolve, reject) {
        var reader = new FileReader();
        reader.onload = function() { resolve(reader.result as string); };
        reader.onerror = reject;
        reader.readAsDataURL(file);
    });
}

您也可以将代码移动到传递给then 调用的回调中,但这可能有点难以阅读(特别是如果您刚开始使用异步代码)并且如果您必须协调多个异步操作快速阅读代码成为问题

async ngAfterViewInit() {
    let image = new Image();
    this.getBase64(fileObject, this.processImage())
        .then(base64=>
        {
            image.src = base64; // available now 

            let editor = new PhotoEditorSDK.UI.ReactUI({
                container: this.editor.nativeElement
                editor: { image }
            });
        });
}

【讨论】:

    【解决方案2】:

    由于代码本质上是异步,如果你想使用它,你必须等待结果。在您的情况下,您将不得不等到您的承诺得到解决。所以你的代码应该是这样的:

    ngAfterViewInit(): void {
       let image = new Image();
       var promise = this.getBase64(this.fileObject, this.processImage);
       promise.then(function(base64: string) {
           console.log(base64);    
           image.src = base64;
    
           let editor = new PhotoEditorSDK.UI.ReactUI({
               container: this.editor.nativeElement
               editor: {
                 image: image
               }
           });
       });
    }
    

    我更改了以下内容:

    1. 我将 ReactUI 实例化的代码移到了 Promise 回调中
    2. base64参数的指定类型为string
    3. 修正了 getBase64 函数调用中的拼写错误,从 this.processImage()this.processImage,因此它传递的是回调函数,而不是 processImage 函数的结果。

    我希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      promise.then是一个异步函数,这意味着该语句之后的代码将首先执行,然后将执行then内的回调函数。所以,你应该把你的代码移到then的回调中。

      promise.then((base64: string) => {
          console.log(base64);    // outputs string e.g 'data:image/jpeg;base64,........'
          console.log(typeof base64); // type is string
          image.src = base64;
      
          let editor = new PhotoEditorSDK.UI.ReactUI({
              container: this.editor.nativeElement
              editor: {
                 image: image
              }
          });
      });
      

      编辑:我将回调函数更改为粗箭头函数() =&gt; {},这是因为您正在通过this.editor 访问组件字段之一,而functions 有自己的范围。您可能会收到一条错误消息:cannot read nativeElement of undefined

      【讨论】:

      • 似乎可以工作,但是我得到了Type '{}' is not assignable to type 'string',即使我确定 base64 变量是一个字符串。我还将图像声明为任何图像,例如public image: any - 为什么我在编辑器中收到打字稿错误? (虽然它似乎在运行......)
      • 您可以明确定义base64 字符串,因为您知道在运行时它将是一个字符串。所以试试function(base64: string)
      猜你喜欢
      • 1970-01-01
      • 2017-09-08
      • 2014-07-16
      • 1970-01-01
      • 2012-08-03
      • 2013-04-24
      • 1970-01-01
      • 2021-12-22
      • 2015-03-16
      相关资源
      最近更新 更多