Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cancel a HTTP request inside an Observable.create

Tags:

angular

rxjs

I am using Angular 2 rc3.

I have a service which returns an rxjs Observable, inside of which there are some async tasks and then a recursive HTTP request. It is a chunked upload, so there are multiple sequential requests each triggered in the success handler of the previous chunk.

I would like to know how to cancel the internal HTTP request when I dispose the containing Observable.

This is basically what I'm doing (not real code):

// UploadService

upload (file) {
    return Observable.create((observer) => {

        let reader = new FileReader();

        // convert file into chunks
        let chunkedFile = this.chunkFile(file);

        reader.onloadend = (event) => {

            // THIS IS THE REQUEST I WANT TO CANCEL
            this.http.put('url/to/upload/to', chunkedFile.currentChunk)
                .subscribe((res) => {

                    // emit some data using containing observable, e.g. progress info
                    observer.next(res);

                    // trigger upload of next chunk
                    this.uploadFileInChunks(reader, chunkedFile, observer);

                });
        };

        // this triggers the onloadend handler above
        this.uploadFileInChunks(reader, chunkedFile, observer);
    });
}

And then I use it in my component like this:

// ExampleComponent

upload () {
    this.uploader = this.uploadService.upload(file)
        .subscribe((res) => {
            // do some stuff, e.g. display the upload progress
        })
}

ngOnDestroy () {
    // when the component is destroyed, dispose of the observable
    this.uploader.dispose();
}

I can see in the network panel that after destroying the component the upload progress still continues.

How can I cancel it?

If it helps to understand the upload, then I'm using this https://github.com/kinstephen/angular-azure-blob-upload ported to Angular 2

like image 939
Daniel Crisp Avatar asked Jan 06 '23 19:01

Daniel Crisp


1 Answers

You need to return a function within the observable creation callback. This function will be called when calling the dispose method:

return Observable.create((observer) => {
  (...)

  return () => {
    // code to dispose / cancel things 
  };
});

To cancel the request within the uploadFileInChunks method, you need to save the subscription and call its unsuscribe method.

reader.onloadend = (event) => {
  // THIS IS THE REQUEST I WANT TO CANCEL
  this.subscription = this.http.put('url/to/upload/to', chunkedFile.currentChunk)
         .subscribe((res) => {
           // emit some data using containing observable, e.g. progress info
           observer.next(res);

           // trigger upload of next chunk
           this.uploadFileInChunks(reader, chunkedFile, observer);

         });
};

() => {
  if (this.subscription) {
    this.subscription.unsubscribe();
  }
}
like image 117
Thierry Templier Avatar answered Jan 21 '23 07:01

Thierry Templier