如何从 React 应用程序停止 node.js 上的 运行 异步功能?

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

React 应用程序可以运行 node.js 批量准备数据并将信息发送到数据库的功能。 这需要很多时间,我想添加直接从 React 应用程序停止此功能的功能。

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;

我尝试了很多东西来包含在这个函数中,包括:

之后:

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);
}

出于某种原因,这不会迭代。

有解决办法吗? 谢谢!

要中止 do/while 循环,您需要向该循环添加一个额外的测试,该测试是一些可以从外界修改的变量。另外,请注意附加测试仅适用于此处,因为您在循环内使用 await 。如果循环内没有 await,那么循环将是完全同步的,并且在循环为 运行 时无法从循环外部更改变量(因为 nodejs 的单-螺纹)。

由于这是一个服务器(全局变量通常不好),我假设我们不应该使用全局变量。因此,相反,我会将 addOrdersToDB() 重组为 return 一个数据结构,其中包含现有版本 returns 的承诺和调用者可以调用以停止当前版本的 abort() 函数加工。这也允许对 addOrdersToDB() 的多个单独调用是 运行,每个调用都有自己单独的 abort() 方法。

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);

            // make resolved value be a boolean that indicates
            // whether processing was stopped with more work still pending
            return !!(latestOrd && stop);

        } catch (err) {
            // log error and rethrow so caller gets error propagation
            console.log(err);
            throw err;
        }
    }
    return {
        promise: run(),
        abort: abort
    }
}

因此,要使用它,您必须更改调用 addOrdersToDB() 的方式(因为它不再 return 只是一个承诺)并且您必须捕获 abort() 函数,它 returns。然后,您的代码的其他部分可以调用 abort() 函数,然后它将翻转内部 stop 变量,这将导致您的 do/while 循环停止任何进一步的迭代。

请注意,这不会停止 do/while 循环当前迭代内的异步处理 - 它只会停止循环的任何进一步迭代。

请注意,我还更改了您的 catch 块,以便它重新抛出错误,以便调用者看到 if/when 出现错误。

并且,函数的解析值是内部 stop 变量,因此调用者可以查看循环是否中止。 true 已解决的值意味着循环已中止,还有更多工作要做。


这是该函数的一个附加版本,它创造了更多机会使其在函数内和循环内的 await 操作之间停止。这仍然不会中止可能正在进行的单个数据库操作 - 您必须检查您的数据库是否支持此类操作,如果支持,如何使用它。

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');

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

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

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

            // make resolved value be a boolean that indicates
            // whether processing was stopped with more work still pending
            return !!(latestOrd && stop);

        } catch (err) {
            // log and rethrow error so error gets propagated back to cller
            console.log(err);
            throw err;
        }
    }
    return {
        promise: run(),
        abort: abort
    }
}