使用异步承诺时,如何捕获HTML5 FileReader的结果?

8

我有一个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() {

}

2
为什么不把 let image = new Image();image.src = base64; 放在 Promise 回调函数里面呢? - sloth
1
将其移动到 promise.then 或使用 async await?+400 上的问题是什么? - yurzui
你想使用 Promise,但又不想等待其完成。 - zaheer
3个回答

8

由于getBase64是一个异步操作,你不能立即使用它的结果。你需要等待它,可以通过调用then(就像你已经尝试过的那样),或使用async/await

async/await版本(也是es 2017标准的一部分)更容易理解,特别是对于新手来说。一个通用的规则是,如果你看到一个Promise并且需要使用它的值,则需要使用await运算符(并将方法设为async)。

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

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

编辑:我将回调函数更改为箭头函数() => {},这是因为你正在通过this.editor访问其中一个组件字段,并且function具有自己的范围。你可能会收到错误消息,指出无法读取未定义的nativeElement


似乎工作正常,但我收到了Type '{}' is not assignable to type 'string'的错误提示,尽管我确定base64变量是字符串。我也将图像声明为任意类型,例如public image: any - 为什么我的编辑器会出现typescript错误?(虽然它似乎可以运行...) - Zabs
1
你可以明确定义 base64 字符串,因为你知道它在运行时将是一个字符串。所以尝试使用 function(base64: string) - Bunyamin Coskuner

3

由于代码的本质是异步的,如果你想使用它,你必须等待结果。在你的情况下,你需要等待promise被解决。所以你的代码应该像这样:

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 函数的结果。
希望这有所帮助!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接