Home > Net >  Is there a way to abort an executing asynchronous function from outside the function in JavaScript?
Is there a way to abort an executing asynchronous function from outside the function in JavaScript?

Time:08-02

I have an asynchronous function that takes some time to complete execution. Before it is able to do so, it can be called again with new data, in which case the previous call isn't necessary anymore, so I want to abort it. I'm looking for a solution that doesn't require me to add something like if (abort_function) return; after each instruction in the function.

I have tried to understand how the AbortController interface works to see if it was able to do just that, but I couldn't get it to abort the function and I'm unsure if it's able to or if it's for something similar but different (to abort an asynchronous server fetch and a single Promise being awaited, I think).

Here's a minimal example of the problem:

const input = document.createElement('input');
const div = document.createElement('div');
const sleep = milliseconds => new Promise(resolve => setTimeout(resolve, milliseconds));
const on_input = async () => {
  const value = input.value;
  console.log(`Asynchronous function started. Value: ${value}.`);
  for (let index = 1; index <= 10; index  ) {
    await sleep(500);
    console.log(`${index * 10}% completed. Value: ${value}.`);
  }
  div.textContent = value;
};
input.addEventListener('input', on_input);
document.body.append(input, div);

CodePudding user response:

There's no way to interrupt a running function at an arbitrary point. Part of the issue here is that unless you're spawning another process (workers), non-IO work is happening in a single thread.

To leverage AbortController, or any other abort pattern, you do need to check if the signal has been aborted at various "checkpoints" in your abortable function.

An example of AbortController:

function f(signal) {
    console.log('Some work.')
    signal.throwIfAborted()
    console.log('More work.')
    signal.throwIfAborted()
    console.log('Even more work.')
}

const abortController = new AbortController()
setTimeout(() => f(abortController.signal), 500)

abortController.abort()
  • Related