简体   繁体   中英

How to stop running async function on node.js from react application?

React app can run node.js function which preparing data and sending information to the database in batches. It takes a lot of time and I would like to add the ability to stop this function right from react app.

const getShopifyOrders = require('./shopify');
const getTrack = require('./tracking');
const Order = require('./model');

async function addOrdersToDB(limit) {
  try {
    // Get latest order from DB
    let latestOrd = await Order.findOne().sort('-order_number');

    do {
      // Get Shopify Orders
      let orders = await getShopifyOrders(
        latestOrd ? latestOrd.order_id : 0,
        limit
      );
      latestOrd = orders[0] ? orders[orders.length - 1] : undefined;

      // Update array with tracking status
      let fullArray = await getTrack(orders);

      // Add to DB
      let ins = await Order.insertMany(fullArray, { ordered: false });
      console.log(`Added ${ins.length} entries`);
    } while (latestOrd);
  } catch (err) {
    console.log(err);
  }
}
module.exports = addOrdersToDB;

I tried a lot of things to include in this function including:

  • while loop: added the variable outside the function - if 'true' - run code, if not - return - it just doesn't work (variable was changed from react using socket.IO)

  • setTimeout (also setInterval), triger clearTimeout function from react: this doesn't work as setTimeout and setInterval doesn't work in async function

after that:

  • made (actually fond here on stackoverflow) new function to promisify setTimeout to be able to use in async function:
const setTimeout2 = (callback, ms) => {
  return new Promise(
    resolve =>
      (to = setTimeout(() => {
        callback();
        resolve();
      }, ms))
  );
};
async function addOrdersToDB(limit) {
  do {
    await setTimeout2(async () => {
      try {
        // some code here
      } catch (err) {
        console.log(err);
      }
    }, 400);
  } while (latestOrderExist);
}
function clearTO() {
  setTimeout(() => {
    console.log('clearTO');
    clearTimeout(to);
  }, 3000);
}

This for some reason doesn't iterate.

Is there solution for this? Thanks!

To abort the do/while loop, you will need to add an additional test to that loop that is some variable that can be modified from the outside world. Since this is a server, I will assume we should not use a global so instead, I would restructure addOrdersToDB() to return a data structure that contains both the promise the existing version returns and an abort() function the caller can call to stop the current processing.

function addOrdersToDB(limit) {
    let stop = false;

    function abort() {
        stop = true;
    }

    async function run() {
        try {
            // Get latest order from DB
            let latestOrd = await Order.findOne().sort('-order_number');

            do {
                // Get Shopify Orders
                let orders = await getShopifyOrders(
                    latestOrd ? latestOrd.order_id : 0,
                    limit
                );
                latestOrd = orders[0] ? orders[orders.length - 1] : undefined;

                // Update array with tracking status
                let fullArray = await getTrack(orders);

                // Add to DB
                let ins = await Order.insertMany(fullArray, { ordered: false });
                console.log(`Added ${ins.length} entries`);
            } while (!stop && latestOrd);
            return stop;
        } catch (err) {
            console.log(err);
            throw err;
        }
    }
    return {
        promise: run(),
        abort: abort
    }
}

So, to use this, you would have to change the way you call addOrdersToDB() (since it no longer returns just a promise) and you would have to capture the abort() function that it returns. Then, some other part of your code can call the abort() function and it will then flip the internal stop variable that will cause your do/while loop to stop any further iterations.

Note, this does not stop the asynchronous processing inside the current iteration of the do/while loop - it just stops any further iterations of the loop.

Note, I also changed your catch block so that it rethrows the error so that the caller will see if/when there was an error.

And, the resolved value of the function is the internal stop variable so the caller can see if the loop was aborted or not. A true resolved value means the loop was aborted.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM