Gil Epshtain
Gil Epshtain

Reputation: 9801

How to Abort (Stop) a chain of promises, executed in a loop? - JavaScript

I have a web application, in which I have two buttons: "start download" and "abort download", that are bind to the methods: start() and stop() accordingly.
1. When the user clicks the "start download" button, the application will loop over an array of data. For each item in the array, it will call the _downloadFile() method that will download one file and return a new Promise(), once that download is complete the next download will start.
2. If during the download flow (that may take a long long time) the user clicked the "abort download" button I would like to stop the download flow.

How can I implement the abort functionality?
Here is what I got so far?

Notice that due to the fact I'm using async/await, the loop will holt until the promise is resolved, and the next iteration will only be executed once the promise is resolved (or rejected).

async function start(dataArray)
{
  for (let i = 0; i < dataArray.length; i++)
  {
    try
    {
      let fileUrl = `http://server-url/${ i }/${ dataArray[i] }.xml`;
      let result = await _downloadFile(fileUrl);
      _saveResult(result);
    }
    catch(e) // promise rejected
    {
      _handleError(e);
    }
  }
}

function stop()
{
  // what goes here?? how do I stop the flow??
}

function _downloadFile(fileUrl)
{
  return new Promise((resolve, reject) =>
  {
    // ...
  });
}

function _saveFile(data) 
{
  // ..
}

function _handleError(error)
{
  console.error("Error: " + error);
}

Upvotes: 2

Views: 359

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074038

Set a flag that the function can check, and throw if it's set. (Well, you're actually converting rejection to resolution in your code, so maybe you don't throw, just return early. [I wouldn't do that, btw.])

let stopped = false; // *** The flag
async function start(dataArray)
{
  stopped = false;                                  // *** Re-init the flag
  for (let i = 0; i < dataArray.length; i++)
  {
    try
    {
      let fileUrl = `http://server-url/${ i }/${ dataArray[i] }.xml`;
      let result = await _downloadFile(fileUrl);
      if (stopped) {                                // *** Check the flag
          return;                                   // *** and return
      }
      _saveResult(result);
    }
    catch(e) // promise rejected
    {
      _handleError(e);
    }
  }
}

function stop()
{
  // *** Set the flag
  stopped = true;
}

Upvotes: 2

Related Questions