Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to preserve the 'this' instance in a callback function

In Angular2 I have a component that uses a service for uploading a file to Amazon S3.

My component (simplified):

private _loading = true;

// use service to upload file
this._s3service.uploadFile(fileObject, this.uploadCallback)

// use this function as a callback
uploadCallback(err, data) {
  this._loading = false; // this crashes because of 'this' is referring to service instead of component
} 

My service (simplified):

    private getS3(): any {
       // Get or create AWS instance
       return s3;
    }

    public uploadFile(selectedFile, callback): boolean {
       this.getS3().upload({
            Key: key_name,
            ContentType: file.type,
            Body: file,
            StorageClass: 'STANDARD',
            ACL: 'private'
          }, function(err, data){ // <=== What to do here?!
            callback(err, data)
          });
    }

The problem is that when the callback function is fired from the service, this is referring to the service and this._loading cannot be found.

Question: How can I preserve the this instance in my callback function, (this in the callback must point to component and not service)

like image 797
Vingtoft Avatar asked Dec 11 '22 12:12

Vingtoft


1 Answers

Use arrow functions

  }, (err, data) => { // <=== What to do here?!

they are for exactly that purpose, for this to keep pointing at the class instance where the function is declared.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

If you pass a function reference .bind(this) might be more convenient, because it doesn't require to list the parameters at all while => would require them twice

myCallback(err, data){ // <=== What to do here?!
        callback(err, data)
}

public uploadFile(selectedFile, callback): boolean {
   this.getS3().upload({
        Key: key_name,
        ContentType: file.type,
        Body: file,
        StorageClass: 'STANDARD',
        ACL: 'private'
      }, this.myCallback.bind(this));
}

The same which arrow functions

public uploadFile(selectedFile, callback): boolean {
   this.getS3().upload({
        Key: key_name,
        ContentType: file.type,
        Body: file,
        StorageClass: 'STANDARD',
        ACL: 'private'
      }, (err, data) => this.myCallback(err, data));
}
like image 130
Günter Zöchbauer Avatar answered Dec 13 '22 23:12

Günter Zöchbauer