Why You Need an API Layer
3. Easily handle request cancellation
Thanks to the centralized nature of the API layer, you can effortlessly add custom features like cancellation to all API request definitions.
Your frontend application performs API calls asynchronously. This means that when calling the same API twice in a short amount of time, the response to the first request may arrive after the response to the second one. Because of this, your application may render inconsistent data.
A popular approach to deal with this problem is the debounce technique. The idea behind debounce is to wait a certain amount of time before executing the same operation twice. Implementing this and finding the right debounce time value for each scenario, however, is not easy. For this reason, you should consider API request cancellation. With request cancellation, the new API request simply cancels the previous one of the same type.
API request cancellation is simpler than debouncing and more useful. As you are about to see, adding such a feature to an API layer is easy and only requires a few lines of code. Considering that you might need request cancellation only in specific circumstances, the functions in your API layers should always pass a cancel
boolean parameter to enable it as follows:
export function defineCancelApiObject(apiObject) { // an object that will contain a cancellation handler // associated to each API property name in the apiObject API object const cancelApiObject = {} // each property in the apiObject API layer object // is associated with a function that defines an API call // this loop iterates over each API property name Object.getOwnPropertyNames(apiObject).forEach((apiPropertyName) => { const cancellationControllerObject = { controller: undefined, } // associating the request cancellation handler with the API property name cancelApiObject[apiPropertyName] = { handleRequestCancellation: () => { // if the controller already exists, // canceling the request if (cancellationControllerObject.controller) { // canceling the request and returning this custom message cancellationControllerObject.controller.abort() } // generating a new controller // with the AbortController factory cancellationControllerObject.controller = new AbortController() return cancellationControllerObject.controller }, } }) return cancelApiObject }