I am working on one angular project in which I have file upload feature is implemented. I have created one upload service and make one function inside it for upload file
service.ts :
upload(file: File){
return new Promise(resolve=>{
var file = file;
bucket.upload(file).on("httpUplaodprogress", (progress)=>{
const percent = progress.percent
--> Here I want to emit this percent value from this function. and want to get it where it is from called.
}).send(response =>{
response.error ? reject(response.err);
resolve(response);
})
})
}
Now this upload service is used at many place.
E.g :
uploadComponent.ts :
progress:number = 0;
constructor(private uploadService: UploadService) {}
handleFileInput(file){
this.uploadService.upload(file).then(result=>{
result ? show success msg for file uplaod success : show error
==> I want to subscribe service's upload function's progress variable
here for assign that value into this host component's progress variable which is
bind with progressbar copmponent.
})
}
uploadComponent.html
<progressbar [progress]="progress" />
This is current scenario where we can't access progress variable from service function into host component where service function is called.
one way is that, we can get subscribe service function into host component and can progress value can continuously get. but how ?
because service function already return promise. how can I use subscription inside promise and subscribe it into host component.
I had also thought about global subscription variable into service and subscribe it into host component. but it can cause problem when upload file from multiple places and show progressbar.
I want to keep subscription variable's scope local for each call.
If anyone know about it, how to broadcast value from promise function and receive at host function from where it is called.. then please reply this. It's very helpful for me.
Your should return an Observable from your service instead of a Promise.
UploadService
// note that BucketUploadResponse is an interface I made up
upload(file: File): Promise<BucketUploadResponse> {
// delegate to our Observable implementation and convert to promise
return this.upload$(file).toPromise();
}
// note that BucketUploadResponse is an interface I made up
upload$(file: File): Observable<number | BucketUploadResponse> {
return new Observable<number>((subscriber) => {
bucket
.upload(file)
.on('httpUplaodprogress', (progress) => {
const percent = progress.percent;
// emit progress
subscriber.next(percent);
})
.send((response) => {
if (response.error) {
// error out
subscriber.error(response.error);
} else {
// emit response as last item to keep old contract
subscriber.next(response);
subscriber.complete();
}
});
return () => {
// called when no subscription is left. You could abort the upload here for example
};
});
}
In the consuming component, you can subscribe to the Observable:
progress:number = 0;
private uploadSubscription?: Subscription;
constructor(private uploadService: UploadService) {}
handleFileInput(file){
this.progress = 0;
// unsubscribe from an existing upload
this.uploadSubscription?.unsubscribe();
this.uploadSubscription = this.uploadService.upload(file).subscribe((progress) => {
if (typeof progress === 'number') {
this.progress = progress;
} else {
// handle BucketUploadResponse if required
}
}, () => {
// complete, show success message
}, (error) => {
// error, show error message
})
}