Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cancel Async/Await

I have a function like below

function async populateInventories(custID){
    this.inventories = await this.inventoryService.getCustomerInventories(custID)

    //do some stuff with Inventories

    // another await 

}

My Problem is I need to cancel a Ongoing Await request, and send a Fresh Await request like we do Using Subscription.

Previously my Function was like below where in i was able to cancel Previous subscription:

function async populateInventories(custID){

    let invetroySubscription$;

    if(invetroySubscription$!==undefined){
        invetroySubscription$.unsubscribe();
    }

    invetroySubscription$=this.inventoryService.getCustomerInventories(custID).subscribe((data:any)=>{
        this.inventories = data.response;

        //do some stuff with Inventories


         // another subscription here -- I was told this way of doing is wrong

    })

}

With async/await i was able to handle any operation sequentially which is really great and code was very much readable with which i was not able to achieve using subscriptions but async/await came with their own drawbacks.

I can stop Multiple Calls at a time to populateInventories to Avoid my problem, But i am looking if i can get any more solutions(neat) to my problem.

PS:I read calling another subscription in a subscribe call or nested subscriptions is not a good Practice.

like image 601
saikiran Avatar asked Jan 05 '20 14:01

saikiran


People also ask

How do I cancel a task in C#?

Cancel(); Console. WriteLine("\n\nPress any key to stop the task");

Why do we need cancellation token?

A CancellationToken enables cooperative cancellation between threads, thread pool work items, or Task objects.

What is CancellationTokenSource in C#?

A CancellationTokenSource object, which provides a cancellation token through its Token property and sends a cancellation message by calling its Cancel or CancelAfter method. A CancellationToken object, which indicates whether cancellation is requested.


Video Answer


1 Answers

Handling the cancellation of an asynchronous actions depends on the type and the way we are executing the async action.

I assume that the type of our asynchronous actions are HTTP requests. Therefor we have several options how we execute a actual HTTP request:

  1. using HttpClient from Angular itself (most common case and the best practice!)
  2. using Axios (afaik a wrapper around the Fetch API)
  3. using Fetch API provided by the browser itself

HttpClient

When using the HttpClient service from Angular itself it is recommended to use it with RxJs in combination. So in your case I would switch back to the Observable solution you have described above. Why?:

  • HttpClient itself uses RxJs and returns Observables as a default
  • RxJs in combination with the HttpClient makes it "easy" to cancel an ongoing request with its switchMap operator
  • Be aware that switchMap itself does not cancel the HTTP request or keeps the logic for it. It just calls unsubscribe on the subscription of the inner stream. The request cancel logic is provided by the implementation of HttpClient (more or less) which returns the cancellation logic in the unsubscribe callback.
  • Unfortunately it's not that easy to write proper RxJs code and avoid multiple or nested subscriptions. In your case I would try to create a stream of (I assume) click events and use:
    • switchMap to flatten the stream (compareable to flatMap) and unsubscribe from an existing inner stream in case a new click-event occurs.
    • concatMap to wait until the completion of the inventoriesRequest stream, before the populateInventoriesRequest is made.
 this.populateInventoryClicks$
  .pipe(
    switchMap(() => this.inventoryService.inventoriesRequest()),
    concatMap(inventories => this.inventoryService.populateInventoriesRequest(inventories)),
  )
  .subscribe(response => {
    console.log(response);
});

Please take a look at the Stackblitz example. Throttle your speed in the network tab in the dev console. In the network tab we should then see that on multiple button clicks only the last request is completed and that all before got canceled. enter image description here


Axios

When using the Axios client, we can use the cancel method it provides for us. Take a look at their documentation if your interested in their approach. Be aware that when we are using Axios no HttpInterceptors from Angular will run on these requests. This is the most obvious reason why I know nobody using it in combination with Angular.


Fetch API

The Fetch API also provides us with the possibility to abort an ongoing request made with fetch. I can't recommend this approach for the same reasons I can't recommend the Axios approach. But take a look at it if you are interested.

like image 75
ChrisY Avatar answered Sep 30 '22 03:09

ChrisY