npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cancjs/axios

v1.0.0

Published

Cancelable promise adapter for axios.

Readme


Introduction

A drop-in replacement for the axios default export whose request methods return a CancelablePromise. Calling .cancel() aborts the request and rejects with a CancelError, so cancellation reads as an ordinary rejection in try/catch.

The wrapper holds no state of its own. It forwards to a real axios instance, so config merging, header handling, interceptor chains and create() seeding are still axios's own code.

Features

  • same call shapes and signatures as axios, including the full AxiosResponse result
  • .cancel() aborts the in-flight request through an AbortSignal
  • cancellation is supported through the full request lifecycle, including interceptors
  • a caller-supplied config.signal also rejects with a CancelError
  • instances from create() are wrapped too, with their own defaults and interceptors
  • works with the xhr, http and fetch adapters, and with axios 0.22 and up
  • no Proxy, ES5-friendly output

Getting Started

Installation

npm install @cancjs/axios axios @cancjs/promise

axios (0.22 or later) and @cancjs/promise are peer dependencies. This package is ecosystem tier: a minor release can carry a breaking change, so pin it with a tilde, ~1.4 (pin the minor, not ~1.x, which npm expands to the same range as ^1), rather than the default caret. See Versioning for the full policy.

Usage

import cancelableAxios from '@cancjs/axios';
import { isCancelError } from '@cancjs/promise';

const promise = cancelableAxios.get('/issues', { params: { q: 'bug' } });

promise.cancel('superseded');

try {
  const response = await promise;
  console.log(response.data);
} catch (error) {
  if (isCancelError(error)) {
    // the request was aborted
  }
}

An instance keeps its own defaults and interceptors, exactly like axios.create():

const api = cancelableAxios.create({ baseURL: 'https://api.example.com' });

api.defaults.headers.common['Authorization'] = 'Bearer token';

The default export and the named cancelableAxios export are the same binding, so import cancelableAxios from '@cancjs/axios' and import { cancelableAxios } from '@cancjs/axios' give you the identical object. Pick whichever reads better next to your existing axios import.

An axios instance built elsewhere can be wrapped instead:

import axios from 'axios';
import { cancelableAxios } from '@cancjs/axios';

const axiosInstance = axios.create({ baseURL: 'https://api.example.com' });
const api = cancelableAxios.wrap(axiosInstance);

In a coroutine the request joins the surrounding cancellation:

import * as canc from '@cancjs/coroutine';

const loadIssues = canc.async(function* (query: string) {
  const response = yield* canc.await(
    api.get('/issues', { params: { q: query } })
  );
  return response.data;
});

const pending = loadIssues('bug');
pending.cancel(); // aborts the request

How It Works

Each request method (get, post, put and the rest) creates its own AbortController, merges the signal into the request config, and returns a CancelablePromise. Canceling the promise aborts that controller, so axios handles the transport-level abort through whichever adapter it is using (xhr, http or fetch).

Cancellation is supported through the full lifecycle of a request, not just the network call. When a request is canceled, interceptors that are still running are canceled too. An interceptor that returns a cancelable promise has that promise canceled along with the request, so work started in an interceptor (a token refresh, a retry) does not keep going after the caller has walked away.

An existing config.signal from the caller is composed with the internal one. Either source can abort the request, and in both cases the promise rejects with a CancelError, normalizing the error regardless of which signal aborted.

The wrapper holds no state beyond what axios itself holds. defaults on the wrapper is a live accessor onto the underlying instance's defaults, and interceptors is a facade over the real interceptor managers, so IDs stay valid and interceptors added directly on the underlying instance still run. create() returns another wrapped instance with its own defaults and interceptors, and wrap() wraps an existing axios instance without creating a new one.

Description

Interceptors

Interceptors receive a second argument carrying the cancellation context of the request they run for. The context exposes signal, isCanceled(), cancel() and link(promise):

api.interceptors.request.use((config, ctx) => {
  if (ctx.isCanceled()) {
    return config;
  }

  return refreshToken({ signal: ctx.signal }).then((token) => {
    config.headers.Authorization = `Bearer ${token}`;
    return config;
  });
});

A cancelable promise returned from an interceptor is canceled along with the request. In the example above, if the request is canceled while the token refresh is in flight, the refresh promise is canceled too. ctx.link(promise) explicitly ties any cancelable promise to the request's lifecycle, so work started outside the return path is still canceled with the request.

Combinators

all differs from axios.all on purpose: it builds a CancelablePromise, so canceling one request rejects the aggregate and cancels the rest. spread is unchanged.

Accessing the underlying instance

The wrapped instance is reachable as .axios when a plain native promise is needed, for example when handing a request to code that does not understand cancellation.

API

cancelableAxios is both the default export and a named export (both references point to the same instance). It mirrors the full axios interface: request, get, delete, head, options, post, put, patch, getUri, create, defaults, interceptors, all, spread.

cancelableAxios.create(config?) returns a new wrapped instance.

cancelableAxios.wrap(axiosInstance) and wrapAxios(axiosInstance) wrap an existing axios instance. The argument is structurally typed, so it accepts instances from any axios version without type conflicts.

CancelScope is the per-request cancellation scope class managing request lifecycle and interceptor promises.

.axios on any wrapped instance returns the underlying axios instance.

Members axios added after 0.22 (postForm, putForm, patchForm, AxiosHeaders, HttpStatusCode and the rest) plus standard axios exports (AxiosError, CancelToken, CanceledError, isAxiosError, VERSION, formToJSON, getAdapter, mergeConfig, toFormData) are re-exported.

Compatibility

Axios 0.22 and later, which is when signal support was added. Node.js 18 and later, current browsers. Everything else follows @cancjs/promise.

Documentation

Contributing

You are welcome to participate through issues and pull requests!

License

MIT