Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capture result of HTML5 FileReader when using promises in async

I have an Angular 4 application where I am reading an image & trying to pass the base64 string to another variable - however I am having an issue due to the async nature of this - the image.src is empty and therefore the value has passed correctly to the image object?

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() {

}
like image 225
Zabs Avatar asked Nov 08 '18 15:11

Zabs


1 Answers

Since getBase64 is an async operation you can't use it's result right away. You need to wait for it either by calling then (as you have already experimented with) or using async/await.

The async/await version (which is also part of the es 2017 standard) is simpler to understand especially if you are new to async programming. A general rule of thumb, if you see a Promise and need to use the value you will need to use the await operator (and make your method 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);
    });
}

You can also move your code to the callback passed to a then call, but this may be a bit harder to read (especially if you are just starting out with async code) and if you have to orchestrate multiple async operations reading the code quickly becomes an issue

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 }
            });
        });
}
like image 172
Titian Cernicova-Dragomir Avatar answered Sep 28 '22 20:09

Titian Cernicova-Dragomir