When working with the onload callback, it can fail due to a changed context (this
). JavaScript inherently changes the context in callbacks. In this scenario, in the onload event, this
refers to the same object as reader
. To address this issue, you need to bind the correct context.
RESOLUTION 1
You can bind the appropriate context to the function being passed using the bind method on that function.
getBase64(file: any) {
var reader: FileReader = new FileReader();
reader.onload = function (readerEvt: any) {
var binaryString = readerEvt.target.result;
this.base64Url = binaryString;
this.mimeType = this.base64Url.substring(this.base64Url.lastIndexOf("data") + 5, this.base64Url.lastIndexOf(";"));
this.base64Url = this.base64Url.substring(this.base64Url.lastIndexOf("base64") + 7);
this.addContentAttachment(this.mimeType, this.base64Url);
}.bind(this); // Ensuring the current 'this' is preserved when the function is called.
reader.readAsDataURL(file);
reader.onerror = function (error) {
console.log('Error: ', error);
};
}
RESOLUTION 2
The same problem can be solved by using a variable named self
within the parent scope of the callback. By storing the correct context in the self
variable, we can access it in the callback instead of the default ('corrupted') this
.
getBase64(file: any) {
var reader: FileReader = new FileReader();
var self = this; // Create 'self' with the correct 'this'
reader.onload = function (readerEvt: any) {
var binaryString = readerEvt.target.result;
self.base64Url = binaryString; // Using 'self' instead of 'this'
self.mimeType = self.base64Url.substring(self.base64Url.lastIndexOf("data") + 5, self.base64Url.lastIndexOf(";"));
self.base64Url = self.base64Url.substring(self.base64Url.lastIndexOf("base64") + 7);
self.addContentAttachment(self.mimeType, self.base64Url);
};
reader.readAsDataURL(file);
reader.onerror = function (error) {
console.log('Error: ', error);
};
}
RESOLUTION 3 (credit to @Aleksey L.)
TypeScript offers an automated solution similar to Resolution 2 through its own syntax. This feature allows TypeScript to handle the context automatically, using the variable _this instead of self.
getBase64(file: any) {
var reader: FileReader = new FileReader();
reader.onload = (readerEvt: any) => {
var binaryString = readerEvt.target.result;
this.base64Url = binaryString;
this.mimeType = this.base64Url.substring(this.base64Url.lastIndexOf("data") + 5, this.base64Url.lastIndexOf(";"));
this.base64Url = this.base64Url.substring(this.base64Url.lastIndexOf("base64") + 7);
this.addContentAttachment(this.mimeType, this.base64Url);
};
reader.readAsDataURL(file);
reader.onerror = function (error) {
console.log('Error: ', error);
};
}