Cancel HTTP requests
Having Taquito implemented in composable modules is a design choice to allow users to customize the modules to meet some of their specific needs.
One of these needs might be the ability to cancel HTTP requests to optimize the network. Indeed, Taquito has heavy methods that make a lot of requests to the RPC. For example, in some cases, users might want to cancel almost immediately a call when using it in user interfaces. It is possible to incorporate some logic into the HttpBackend
and RpcClient
classes to fulfill this need.
Here is an example in which we can click the cancel
button during an estimation call to abort all requests. It will throw an exception.
Live Editor
Result
Here are the steps that we implemented to built the precedent example:
- Create a custom
HttpBackend
We created a class calledCancellableHttpBackend
which extended theHttpBackend
class, and we overrode thecreateRequest
method. We used the AbortController to help to abort the fetch requests. We added logic to thecreateRequest
method to handle the abort signal.
import { HttpBackend, HttpRequestFailed, HttpResponseError, STATUS_CODE, HttpRequestOptions } from '@taquito/http-utils';import AbortController from "abort-controller";class CancellableHttpBackend extends HttpBackend {private abortCtrl: AbortController;constructor(){super();this.abortCtrl = new AbortController();}cancelRequest(){this.abortCtrl.abort();};createRequest<T>({ url, method, timeout, query, headers = {}, json = true, mimeType = undefined }: HttpRequestOptions,data?: {}) {return new Promise<T>((resolve, reject) => {[...]request.onabort = function () {reject(new HttpResponseError(`Request canceled`,this.status as STATUS_CODE,request.statusText,request.response,url));};const abort = () => {request.abort();}this.abortCtrl.signal.addEventListener("abort", abort);[...]});}}
- Create a custom
RpcClient
We created a class calledCancellableRpcClient
which extends theRpcClient
class. We passed to its constructor an instance of ourCancellableHttpBackend
class. We also added acancelRequest
method which is used to trigger the abort signal.
import { RpcClient } from '@taquito/rpc';class CancellableRpcClient extends RpcClient {httpBackend: CancellableHttpBackend;constructor(url: string,chain: string = 'main',customHttpBackend: CancellableHttpBackend = new CancellableHttpBackend()) {super(url, chain, customHttpBackend),this.httpBackend = customHttpBackend;}cancelRequest(){this.httpBackend.cancelRequest();}}
- Set the RpcProvider
Then, we set ourCancellableRpcClient
on ourTezosToolkit
instance instead of using the defaultRpcClient
class:
import { TezosToolkit } from '@taquito/taquito';import { InMemorySigner } from '@taquito/signer';const signer: any = new InMemorySigner('your_key');const customRpcClient = new CancellableRpcClient('your_RPC_URL')const tezos = new TezosToolkit(customRpcClient);tezos.setSignerProvider(signer);
- Trigger the abort signal
We linked thecancelRequest
method of theCancellableRpcClient
class to acancel
button. The initiator of the abort signal might be different based on your use cases. Note that the cancelation action is not specific to a method in the example, meaning that all RPC calls will be aborted.
Tezos.rpc.cancelRequest();