2017-03-17 56 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

相關問題