如何保存这个'回调函数中的实例

时间:2017-03-17 09:45:59

标签: javascript angular typescript

在Angular2中,我有一个使用服务将文件上传到Amazon S3的组件。

我的组件(简化):

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
} 

我的服务(简化):

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

问题是,当从服务触发回调函数时,this指的是该服务,并且找不到this._loading

问题:如何在回调函数中保留this实例,回调中的this必须指向component而不是{{1 }})

3 个答案:

答案 0 :(得分:10)

使用箭头功能

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

它们正是出于这个目的,this继续指向声明函数的类实例。

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

如果你传递了一个功能参考 .bind(this) 可能会更方便,因为它根本不需要列出参数,=>需要它们两次

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

与箭头相同的功能

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

答案 1 :(得分:3)

虽然@Gunter是对的,但我认为您希望将this保留在您实际传递给该函数的回调中:

uploadCallback(err, data) {
  this._loading = false; // this is the "this" you want to keep
} 

然后会是这样的:

this._s3service.uploadFile(fileObject, ()=>this._loading = false);
// or 
this._s3service.uploadFile(fileObject, ()=>this.uploadCallback());
// or
this._s3service.uploadFile(fileObject, this.uploadCallback.bind(this));

另请注意,使用Observable而不是传递回调可能会很有趣:

public uploadFile(selectedFile): Observable<any> { // "<any>" because I don't know what is the type of "data"
    return Observable.create((observer) => {
        this.getS3().upload({
            Key: key_name,
            ContentType: file.type,
            Body: file,
            StorageClass: 'STANDARD',
            ACL: 'private'
        }, (err, data)=> {
            if(err)
              observer.error(err);
            else
              observer.next(data);
            observer.complete();
        });
    });
}

然后:

this._s3service.uploadFile(fileObject).subscribe(data=>console.log(data))

答案 2 :(得分:0)

您可以更改uploadFile以返回promise

并从组件中处理错误案例。 像

这样的东西
    public uploadFile(selectedFile): boolean {
        return new Promise((resolve, reject) => {
          this.getS3().upload({
            Key: key_name,
            ContentType: file.type,
            Body: file,
            StorageClass: 'STANDARD',
            ACL: 'private'
         }, function(err, data){ // <=== What to do here?!
            resolve(err, data)
        });
       }
  });

你可以从你的组件中做到这一点

 this._s3service.uploadFile(fileObject).then((err, data)=> {
   this._loading = false;
 });