In the previous post, we saw how to cancel a request using axios in VueJS. So, does cancelling a request really issues a cancellation token to the backend API or does cancelling a request just cancels on the UI only? Let’s find out.
Here is what I’ll do for this post
As a .NET developer, I know .NET framework has CancellationToken
implementation. So, for this post, I’ll create a new .NET
Core app and add a new controller.
So, here is my new controller.
[HttpGet("users")] public async Task<List<User>> GetUsersAsync(CancellationToken cancellationToken) { try { await Task.Delay(TimeSpan.FromSeconds(2), cancellationToken); return new List<User> { new User {Id = 1, Name = "Karthik"}, new User {Id = 2, Name = "Rithvik"} }; } catch (OperationCanceledException canceledException) when (cancellationToken.IsCancellationRequested) { Console.WriteLine(canceledException); throw; } }
So, when the operation is cancelled, I’ll log the exception to the console.
And if we issue a cancellation token to the endpoint while the Delay is in progress, we will fall into the exception as cancellationToken is requested.
I’m using the code from my previous post as we have “Send Request” and “Cancel request” buttons in the UI and all we’ve to change is the API endpoint to get this started.
Here’s the UI code anyway.
<template> <div> <div> <b-button variant="outline-success" @click="send">Send Request</b-button> <b-button variant="outline-danger" :disabled="!requestInProgress" @click="cancelRequest" >Cancel Request</b-button > <b-button variant="outline-info" @click="reset">Reset</b-button> </div> <br /> <p>Request Status: {{ currentState }}</p> <div v-if="users.length > 0"> <div> <h4>Users in the reqres.in</h4> </div> <b-table striped bordered responsive hover :items="users" :fields="fields" > <template #cell(avatar)="data"> <img v-bind:src="data.value" :width="50" :height="50" /> </template> </b-table> </div> </div> </template> <script> import { BTable, BButton } from "bootstrap-vue"; import axios from "axios"; const states = { IDLE: "Idle 🟡", IN_PROGRESS: "In Progress 📀", SUCCEEDED: "Successful ✅", CANCELLED: "Cancelled ❌", }; // const API_URL = "https://reqres.in/api/users?delay=2"; export default { name: "User", components: { BTable, BButton, }, data() { return { fields: ["id", "avatar", "first_name", "last_name", "email"], users: [], request: null, currentState: states.IDLE, }; }, methods: { cancelRequest() { this.cancel(); this.updateState(states.CANCELLED); }, send() { this.users = []; this.updateState(states.IN_PROGRESS); this.cancel(); let axiosSource = axios.CancelToken.source(); this.request = { cancel: axiosSource.cancel }; axios .get("http://localhost:5000/users", { cancelToken: axiosSource.token, }) .then((res) => { this.users = res.data.data; this.updateState(states.SUCCEEDED); }); }, updateState(msg) { this.currentState = msg; this.request = null; }, reset() { this.currentState = states.IDLE; this.cancel(); this.request = null; this.users = []; }, cancel() { if (this.request) this.request.cancel(); }, }, computed: { requestInProgress() { return this.request; }, }, }; </script>
Let’s run both the UI and .net core backend. And here is a demo of it.
And we got our cancellation exception logged when we cancelled the request.
Okay, this looks good. But, let’s see how we can implement the cancellationToken
for database operation
Before we see the cancellation code, let’s see what happens if we don’t use cancellation token.
[HttpGet("users")] public async Task<List<User>> GetUsersAsync(CancellationToken cancellationToken) { await Task.Delay(TimeSpan.FromSeconds(5)); var users = GetUsersFromDbWithoutCancelAsync(); return await users; } private async Task<List<User>> GetUsersFromDbWithoutCancelAsync() { var users = new List<User>(); var cmd = this.MySqlDatabase.Connection.CreateCommand() as MySqlCommand; cmd.CommandText = "SELECT * from users"; cmd.CommandType = System.Data.CommandType.Text; try { using (var reader = (MySqlDataReader)await cmd.ExecuteReaderAsync()) { if (!reader.HasRows) return null; while (await reader.ReadAsync()) { users.Add(new User { Id = reader.GetFieldValue<int>(0), Name = reader.GetFieldValue<string>(1) }); } } } catch (Exception ex) { Debug.WriteLine(users); Debug.WriteLine(ex); throw; } return users; }
I’m using MySQL package for reading the data from database. The GetUsersFromDbWithoutCancelAsync
just returns all the users in our users table.
Here’s the demo of it.
Now, let’s see what would happen if we cancel in the middle of a database operation.
I’ve modified the GetUsersFromDbAsync
method to use the cancellationToken. And here it is.
private async Task<List<User>> GetUsersFromDbAsync(CancellationToken cancellationToken) { var users = new List<User>(); var cmd = this.MySqlDatabase.Connection.CreateCommand() as MySqlCommand; cmd.CommandText = "SELECT * from users"; cmd.CommandType = System.Data.CommandType.Text; try { using (var reader = (MySqlDataReader)await cmd.ExecuteReaderAsync(cancellationToken)) { if (!reader.HasRows) return null; while (await reader.ReadAsync(cancellationToken)) { users.Add(new User { Id = reader.GetFieldValue<int>(0), Name = reader.GetFieldValue<string>(1) }); } } } catch (OperationCanceledException ex) when (cancellationToken.IsCancellationRequested) { Console.WriteLine(users); Console.WriteLine(ex); throw; } return users; }
We passed cancellation token to the ExecuteReaderAsync
and ReadAsync
method to be able to cancel the operation if cancellation is requested at the time of fetching from database.
And in the catch block, when a cancellation is requested, I’ll write all the users fetched to console until cancellation is requested.
Let’s see this in action.
When we cancelled the operation in UI, we got cancellationToken as true in the C# and we logged the data we have to console until the operation is cancelled.
Yes, it does. But, the libraries should also support cancellation operation.
For this post, I’ve used MySQL library to connect to the database. The library method, for example ReadAsync, supports cancellation and we are able to cancel the operation.
Karthik is a passionate Full Stack developer working primarily on .NET Core, microservices, distributed systems, VUE and JavaScript. He also loves NBA basketball so you might find some NBA examples in his posts and he owns this blog.
In this post, we’ll see how to test gRPC Server applications using different clients. And… Read More
In this post, we'll create a new gRPC project in ASP.NET Core and see what's… Read More
In this blog post, we’ll see how to run dotnet core projects without opening visual… Read More
Programmatically evaluating policies is useful when we want to provide access or hide some data… Read More
We saw how we could set up policy-based authorization in our previous article. In this… Read More
What is policy-based authorization and how to set up policy-based authorization with handlers and policies… Read More
This website uses cookies.