Contents of JavaScript

Essential JavaScript tips, tricks, and best practices to improve your coding skills and write more efficient code.

AbortController | Cancel a Promise | Cancel Events | Cancel Timeouts | Cancel APIs

๐Ÿ”น 1. What is AbortController in JavaScript?

Answer: AbortController is a built-in browser API used to abort ongoing asynchronous operations, especially fetch() requests.

const controller = new AbortController(); const signal = controller.signal; fetch('https://api.example.com/data', { signal }) .then(response => response.json()) .catch(err => { if (err.name === 'AbortError') { console.log('Fetch aborted'); } else { console.error(err); } }); controller.abort(); // Cancels the fetch

โœ… Used to cancel requests or operations with cleanup logic.


๐Ÿ”น 2. What is AbortSignal?

Answer: AbortSignal is a property of AbortController that gets passed to the request (e.g., fetch). It's used to monitor the status of the operation and detect if it was aborted.

const controller = new AbortController(); const signal = controller.signal; signal.addEventListener('abort', () => { console.log('Operation was aborted!'); });

๐Ÿ”น 3. Can you cancel a Promise in JavaScript?

Answer: No, JavaScript does not natively support canceling Promises once started. But we can implement a pattern using AbortController or custom logic to simulate cancellation.

Custom cancelable promise:

function cancelablePromise(promise) { let cancel; const wrapped = new Promise((resolve, reject) => { cancel = () => reject('Cancelled'); promise.then(resolve).catch(reject); }); return [wrapped, cancel]; } const [promise, cancel] = cancelablePromise(fetch('https://api.example.com')); cancel(); // Cancels it

๐Ÿ”น 4. How to cancel a fetch request in JavaScript?

Answer: Use AbortController.

const controller = new AbortController(); fetch('/api/data', { signal: controller.signal }); controller.abort(); // Cancels the fetch

๐Ÿ”น 5. How do you cancel event listeners in JavaScript?

Answer: Use removeEventListener.

function handleClick() { console.log('Clicked'); } document.addEventListener('click', handleClick); document.removeEventListener('click', handleClick); // Cancels it

โœ… Always keep a reference to the function to remove it.


๐Ÿ”น 6. How to cancel a setTimeout in JavaScript?

Answer: Use clearTimeout.

const timeout = setTimeout(() => { console.log('Hello after 2s'); }, 2000); clearTimeout(timeout); // Cancels the timeout

๐Ÿ”น 7. How to cancel a setInterval in JavaScript?

Answer: Use clearInterval.

const interval = setInterval(() => { console.log('Tick'); }, 1000); clearInterval(interval); // Stops the interval

๐Ÿ”น 8. Can AbortController be reused?

Answer: No, once abort() is called, the controller becomes permanently aborted. You need a new instance to control another request.


๐Ÿ”น 9. How to cancel multiple fetches using one AbortController?

Answer: You can pass the same AbortSignal to multiple fetch requests.

const controller = new AbortController(); const signal = controller.signal; fetch('/api/1', { signal }); fetch('/api/2', { signal }); controller.abort(); // Cancels both

๐Ÿ”น 10. Use case: Cancel search API requests on input typing

Answer:

let controller; function onSearchInput(e) { if (controller) controller.abort(); // Cancel previous controller = new AbortController(); fetch(`/search?q=${e.target.value}`, { signal: controller.signal }) .then(res => res.json()) .then(data => console.log(data)) .catch(err => { if (err.name !== 'AbortError') { console.error(err); } }); }

๐Ÿ”น 11. How do you cancel async operations like file uploads or streams?

Answer: Depends on the API. Use AbortController or internal flags in custom implementations.


๐Ÿ”น 12. What happens if you call abort() after the request has completed?

Answer: Nothing. The controller will do nothing since the request is already resolved.


๐Ÿ”น 13. Difference between AbortController and custom cancel logic?

FeatureAbortControllerCustom Cancel Logic
Native SupportYes (browser API)No (manual implementation)
Used Forfetch, streams, etc.Any async operation
Cleanup HookYes (abort event)Needs manual setup
ReusabilityNoYou control reuse manually

๐Ÿ”น 14. Can we use AbortController in Node.js?

Answer: Yes, from Node.js v15+, AbortController is available and supported in fetch, stream, fs, etc.

import fetch from 'node-fetch'; const controller = new AbortController(); fetch('https://api.example.com', { signal: controller.signal }); controller.abort();

๐Ÿ”น 15. What other browser APIs support AbortController?

Answer:

  • fetch()
  • ReadableStream
  • WritableStream
  • FileReader
  • WebSocket (partially with polyfills)
  • navigator.sendBeacon() (limited use)
  • Some DOM Events (via libraries or custom abstraction)

๐Ÿ”ธ 16. Can you cancel setTimeout using AbortController?

Answer: Yes, you can build a utility that cancels a setTimeout using AbortController.

function setAbortableTimeout(fn, delay, signal) { const id = setTimeout(() => { if (!signal.aborted) fn(); }, delay); signal.addEventListener('abort', () => { clearTimeout(id); }); } // Usage const controller = new AbortController(); setAbortableTimeout(() => console.log('Runs in 2s'), 2000, controller.signal); controller.abort(); // Cancels the timeout

โœ… This simulates timeout cancellation via AbortController.


๐Ÿ”ธ 17. How to cancel setTimeout in React using useRef?

Answer: In React, useRef is commonly used to store the timeout ID to clean it up.

import { useEffect, useRef } from 'react'; function MyComponent() { const timeoutRef = useRef<number | null>(null); useEffect(() => { timeoutRef.current = window.setTimeout(() => { console.log('Runs in 3s'); }, 3000); return () => { if (timeoutRef.current) { clearTimeout(timeoutRef.current); } }; }, []); return <div>MyComponent</div>; }

โœ… This is a React-friendly way to cancel timeout on unmount or re-render.


๐Ÿ”ธ 18. Alternative to removeEventListener using AbortController

Answer: You can pass an AbortSignal when adding the event listener, and it will automatically remove itself when aborted:

const controller = new AbortController(); window.addEventListener('click', () => { console.log('clicked!'); }, { signal: controller.signal }); controller.abort(); // Automatically removes the event listener

โœ… This is a clean alternative to manually using removeEventListener.


๐Ÿ”ธ 19. Canceling Event Listeners in React?

Answer: In React, useEffect and useRef are commonly used:

import { useEffect } from 'react'; function MyComponent() { useEffect(() => { const handleClick = () => console.log('clicked'); window.addEventListener('click', handleClick); return () => { window.removeEventListener('click', handleClick); // Clean up }; }, []); return <div>Click anywhere</div>; }

Or with AbortController (experimental, works in modern browsers):

useEffect(() => { const controller = new AbortController(); window.addEventListener('click', () => { console.log('clicked'); }, { signal: controller.signal }); return () => controller.abort(); // Auto cleanup }, []);

๐Ÿง  Bonus Interview Questions


๐Ÿ”ธ 20. Whatโ€™s better: AbortController or useRef with clearTimeout?

Answer:

Use CaseBest Tool
Timeouts inside componentsuseRef + clearTimeout
Complex abort logic across modulesAbortController
Multiple listenersAbortController with signal
Legacy support neededuseRef or manual cleanup

Use both where appropriate. Combine them for best results in complex apps.


๐Ÿ”ธ 21. Can we use useRef.current.abort() to cancel operations in React?

Answer: Yes! You can use useRef to persist the AbortController across renders and call .abort() in cleanup functions like useEffect.

This is a React pattern for managing cancellable side effects.


โœ… Example: Cancel API Request on Component Unmount

import { useEffect, useRef } from 'react'; function MyComponent() { const abortControllerRef = useRef<AbortController | null>(null); useEffect(() => { abortControllerRef.current = new AbortController(); fetch('https://api.example.com/data', { signal: abortControllerRef.current.signal, }) .then(res => res.json()) .then(data => console.log(data)) .catch(err => { if (err.name === 'AbortError') { console.log('Fetch aborted'); } else { console.error(err); } }); return () => { abortControllerRef.current?.abort(); // Cancel the fetch on unmount }; }, []); return <div>Data Loading...</div>; }

๐Ÿ”ธ 22. Why use useRef for AbortController in React?

Answer:

  • useRef stores a persistent mutable object across renders.
  • Useful to store a controller that doesn't change when component re-renders.
  • Avoids triggering re-renders unlike useState.

โœ… Ideal for aborting fetches or timers in useEffect.


๐Ÿ”ธ 23. What happens if useRef.current.abort() is called twice?

Answer: Calling .abort() multiple times is harmless. The second and further calls do nothing. Once aborted, the controller is in the "aborted" state permanently.


๐Ÿ”ธ 24. Can I reuse useRef.current.signal for a new fetch?

Answer: โŒ No. Once aborted, the signal is permanently aborted.

โœ… To reuse, you must create a new AbortController:

abortControllerRef.current = new AbortController(); // Replace the old one

๐Ÿ”ธ 25. How do you cancel previous API requests in search input (React)?

Answer:

function SearchComponent() { const abortRef = useRef<AbortController | null>(null); const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { if (abortRef.current) { abortRef.current.abort(); // Cancel previous } abortRef.current = new AbortController(); fetch(`/api/search?q=${e.target.value}`, { signal: abortRef.current.signal, }) .then(res => res.json()) .then(data => console.log(data)) .catch(err => { if (err.name !== 'AbortError') console.error(err); }); }; return <input type="text" onChange={handleInputChange} />; }

โœ… This ensures only the latest input triggers the search.


๐Ÿ”ธ 26. When should you avoid using AbortController with useRef?

Answer:

  • Donโ€™t use it for simple timeouts โ€“ prefer setTimeout + useRef.
  • Donโ€™t store it if you only use fetch once.
  • Avoid if you donโ€™t need to cancel anything.

Use it when:

  • You need to cancel API requests
  • You handle dynamic updates (e.g., user typing)
  • You want cleanup on unmount

๐Ÿ”ธ 27. Is useRef.current.abort() better than clearTimeout()?

Answer: They're for different use cases:

FeatureuseRef + clearTimeoutuseRef + AbortController
For timersโœ… YesโŒ No
For canceling fetch/APIโŒ Noโœ… Yes
Can listen to abortโŒ Noโœ… Yes (via .signal)
Browser-native cancelingโŒ Manualโœ… Native with fetch

Use each where it makes the most sense.