【问题标题】:Waiting for a synchronous function with internal callback等待带有内部回调的同步函数
【发布时间】:2020-06-18 00:45:34
【问题描述】:

我有几个同步函数,其中一些不是我自己的代码。 这些函数在完成时接受并执行回调函数。

我需要等到这些回调完成后再退出应用程序。 我该如何执行?

const serverGracefulShutdown = () => {

  logger.info('Signal received: Gracefully killing application');

  httpServer.close(() => {
    logger.info('Apollo server closed');
  });

  redis.quit(() => {
    logger.info('Redis client closed');
  });

  stopKafkaConsumer(() => {
    logger.info('Kafka consumer closed');
  });

  logger.info('Application closed');
  process.exit(0);
};

process.on('SIGINT', serverGracefulShutdown);
process.on('SIGTERM', serverGracefulShutdown);

在上面的代码中,我想确保应用程序正常关闭。

所有正在运行的东西都停止了,然后我可以调用 process.exit(0)

【问题讨论】:

  • Promsify 一切并使用Promise.all()。否则,您必须实现某种计数器,然后在每个回调中,递减计数器并检查计数器是否已归零,表明所有回调现已完成。
  • 出于某种原因,我认为我只能使用异步函数来实现 Promise。

标签: node.js asynchronous shutdown


【解决方案1】:

你应该可以玩 Promise:

const serverGracefulShutdown = () => {

  logger.info('Signal received: Gracefully killing application');

  const promises = [

    new Promise((resolve, reject) => httpServer.close(() => {
      // do you get an optional error param inside this callback?
      // if yes, then "if (error) reject(error) else resolve()"
      // (or any other way to mark this operation as failed)
      logger.info('Apollo server closed');
      resolve();
    })),

    new Promise((resolve /* + reject? */) => redis.close(() => {
      logger.info('Redis client closed');
      resolve();
    })),

    new Promise((resolve /* + reject? */) => stopKafkaConsumer(() => {
      logger.info('Kafka consumer closed');
      resolve();
    }))

  ];

  return Promise.all(promises).then(() => {
    logger.info('Application closed');
    process.exit(0);
  }).catch((error) => {
    // what's your plan if at least one failed?
  });

};

process.on('SIGINT', serverGracefulShutdown);
process.on('SIGTERM', serverGracefulShutdown);

【讨论】:

  • 这让我有点困惑。代码运行后,我没有什么要“解决”的。我只需要知道内部回调什么时候完成,所以我知道 HTTP 服务器已关闭,我可以关闭 Redis 和 Kafka,之后我可以退出 Node。
  • @MichalFašánek 好吧,“之后我可以退出 Node”对我来说听起来像是一个“解决”:) “一旦所有连接都关闭,停止服务器”:这里有一些异步的东西,你需要在做一些其他事情之前等待一些事情发生,这基本上是 Promise 的工作。无论如何,您不能只是在 Node.js 中以同步方式等待某些东西,所以它要么是回调(就像其他答案建议的那样),要么是(伪装成的回调)承诺 :)
  • 经过一番麻烦,我发现:如果我没有将回调传递给那些退出函数,它们会返回一个 Promise。这对我来说是一个巨大的胜利。现在我的代码很简单并且可以工作。但是没有人费心将其放入文档中。在咨询了我的同事之后,这似乎是 Node.js 中的常见实现。但这真的让我很沮丧,我应该可以在不知道社区的家规的情况下看到这一点。不过谢谢你的知识。
  • @MichalFašánek 哦,那太好了,请随意回答您自己的问题 :) 我猜您仍在使用 Promise#all,不是吗?构建一系列承诺现在应该看起来不那么笨拙了,如果现在是单行的话,甚至可能直接与对 Promise#all 的调用进行内联:)
  • 我使用了 Promise#all,因此我会接受这个答案。我的最终逻辑是:关闭 HTTP 服务器(可能需要 Redis 和 Kafka)-> 然后并行关闭 Redis 和 Kafka -> 然后终止应用程序。可能适用于所有人:检查操作的返回类型。
猜你喜欢
  • 2017-04-07
  • 1970-01-01
  • 2017-06-09
  • 2020-01-29
  • 2021-04-07
  • 2017-03-31
  • 1970-01-01
  • 2021-03-11
  • 1970-01-01
相关资源
最近更新 更多