Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function inside filereader.onload is not being executed in javascript

I am reading the file using filereader and using the base64 to perform some action. I can read the file and get base64 but couldn't use that to make some action. here is my code.

The problem is the code in the line this.addContentAttachment(this.mimeType,this.base64Url) not being executed

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

    reader.readAsDataURL(file);

    reader.onerror = function (error) {
      console.log('Error: ', error);
    };

  }
like image 549
user3154990 Avatar asked Oct 20 '16 04:10

user3154990


1 Answers

It fails in the onload callback due to changed context (this). JavaScript natively change the context in callback. In your case in onload this is the same as reader. You have to bind right context.

SOLUTION 1 You can bing the right context to passed function by 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); // We forced that when function will be called this will be current this.

    reader.readAsDataURL(file);

    reader.onerror = function (error) {
        console.log('Error: ', error);
    };

}

SOLUTION 2 The same would be solved by self variable in parent scope of callback. We use self variable to store right context and then we use it in callback instead of standard ("corrupted" this).

getBase64(file: any) {
    var reader: FileReader = new FileReader();

    var self = this; // create self with right this
    reader.onload = function (readerEvt: any) {
        var binaryString = readerEvt.target.result;
        self.base64Url = binaryString; // using self instead 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);
    };

}

SOLUTION 3 (thanks to @Aleksey L.) TypeScript can automate solution 2 by their own syntax. You can try that and see result in playground, it does the same as described in solution 2, but variable is named _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);
    };

}
like image 87
Misaz Avatar answered Nov 07 '22 07:11

Misaz