在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 }})
答案 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;
});