6

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

  }
3
  • 1
    It probably fail 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. reader.onload = function () { ... }.bind(this); Commented Oct 20, 2016 at 4:18
  • @Misaz..it worked.. thank you so much Commented Oct 20, 2016 at 4:22
  • Another option is to use an arrow function: reader.onload = (readerEvt: any) => { ... } Commented Oct 20, 2016 at 4:50

1 Answer 1

10

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

}
Sign up to request clarification or add additional context in comments.

2 Comments

is type possible without any? It always says that it doesnt expect the .result property to be included
@MarcSlothEastman I am slightly outside TS world and I do not know about any latest news, but I tried it with TS 5.4.5 installed on debian using npm and default config (just tsc file.ts command) and I did not produce any error to me. Could you please explain which version of TS you use and what properties do you set in tsconfig.json? Maybe you use some more restrictive mode. vscode highligh ProgressEvent<FileReader> type to me, but replacing any with it requires aditional work on handling possible ArrayBuffer output.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.