Reputation: 14142
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() {
}
Upvotes: 8
Views: 1846
Reputation: 26075
As the code is asynchronous in nature, you will have to wait for the result if you want to use it. In your case, you will have to wait until your promise is resolved. So your code should look like:
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
}
});
});
}
I have changed following things:
ReactUI
instantiation inside promise callback base64
parameter as string
getBase64
function call, from this.processImage()
to this.processImage
so it is passing callback function and not result of processImage
function.I hope this helps!
Upvotes: 3
Reputation: 250006
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 }
});
});
}
Upvotes: 8
Reputation: 8859
promise.then
is an async function which means the code comes after this statement will be executed first and then callback function within then
will be executed. So, you should move your code into callback of 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
}
});
});
Edit: I changed the callback function to fat arrow function () => {}
, it's because you are accessing one of the component fields by this.editor
, and function
s have their own scope. You may get an error saying cannot read nativeElement of undefined
.
Upvotes: 3