Skip to content

Race condition on immediate requests cancellation (a solution is suggested) #4260

@korniychuk

Description

@korniychuk

Describe the bug

Axios throws an error instead of canceling all requests when I try to cancel multiple requests just after sending them.
Ankor 2021-11-12 at 16 33 51

To Reproduce

Code snippet to reproduce on npm.runkit.com

var axios = require("axios");

const CancelToken = axios.CancelToken;
const source = CancelToken.source();

const promises = Array(5).fill(1).map((v, i) =>
  axios.get('https://www.google.com', { cancelToken: source.token })
       .catch(e => axios.isCancel(e) && console.log(`Req ${ i } is cancelled ${ e && e.message }`))
);

source.cancel('Aborted by user');

await Promise.all(promises);
console.log('Done');

Expected behavior

Should cancel all requests without throwing an error.

Environment

  • Axios Version [0.24.0]
  • Adapter [default maybe, I don't know]
  • Browser [NA]
  • Browser Version [NA]
  • Node.js Version [16.13]
  • OS: [*]
  • Additional Library Versions [no libraries]

Additional context/Screenshots

I've described the issue with the screenshot.
Ankor 2021-11-12 at 16 27 48@2x

Solution

Ankor 2021-11-12 at 16 43 30@2x

  this.promise.then(function(cancel) {
    if (!token._listeners) return;

    var i;
    var l = token._listeners.length;

    /** We have to clone it to avoid a race condition with .unsubscribe() method */
    var clonedListenersArr = token._listeners.concat();
    for (i = 0; i < l; i++) {
      clonedListenersArr[i](cancel);
    }
    token._listeners = null;
  });

Maybe someone has time to create a simple PR. It would be great.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions