2017-03-17 19 views
4

在Angular2中,我有一个使用服务将文件上传到Amazon S3的组件。如何在回调函数中保留'this'实例

我的组分(简化):

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而不是service

+0

可能的解决方法也可能是使用实例函数的https:// github上。 com/Microsoft/TypeScript/wiki /%27this%27-in-TypeScript#use-instance-functions – yurzui

回答

3

虽然@Gunter是正确的,我想你想保持this你actualy传递给函数的回调:

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)) 
+0

你明白我的问题是正确的。 +1建议使用Observable。 – Vingtoft

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

或者,如果由于某些原因您不能或不想使用箭头函数,则可以“绑定”该函数(myFunction(){} .bind(this))。这是ES6之前的做法。 –

+0

我曾考虑添加它,但以问题中的例子来说,我认为这不是一个好主意。我对这个例子进行了修改,使其更有意义。 –

+0

我可能没有问清楚:问题是回调的'this'引用服务而不是组件。我需要回调中的代码用'this'指向组件(而不是服务)来执行。如果我没有看错,你的答案显示如何将“this”绑定到服务。 – Vingtoft

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

为什么要解决(err,data)',为什么不'解析(数据)'和'拒绝(err)'? – n00dl3

+0

@ n00dl3是错误应该被拒绝。但在这种情况下,它将取决于上传函数调用 – lintu

+0

的响应参数,问题是什么? '(err,data)=> err?reject(err):resolve(data)' – n00dl3

相关问题