【问题标题】:SetTimeout and setInterval in an asynchronous function异步函数中的 SetTimeout 和 setInterval
【发布时间】:2020-06-29 19:50:05
【问题描述】:
   var processStatusCheck = setInterval(function statusCheck() {
    sequelize.query(dbQuery).then(function (data) {
       winston.info(' Status:', importStatus);
      if (importStatus ===  true) {
        winston.info('Inside', pollCount);
        clearInterval(processStatusCheck);
        addProcess(Id, function (response) {
               res.send(200)
        });
      } else {
        if(pollCount > 15){
          winston.info('It came here !!!', pollCount);
           res.sendStatus(500);      
        }else{
          winston.info('Incrementing.....');
          pollCount++;
          setTimeout(statusCheck, 18000);
        }
      }
    });
  }, 5000);

我正在尝试实现一个异步 Javascript 函数。我想不断地查询数据库,直到状态变为真,

最初调用是在 5 秒后根据 setInterval 进行的,但一旦达到 setTimeout,它就会连续调用该函数。我希望它在 18 秒后被调用。 如果 setTimmeout 中的时间少于 5 秒,则会立即发送响应,并且我收到“发送后无法设置标头”错误。

这里有 setInterval 和 setTimeout 导致我出现问题吗?请指导我。

【问题讨论】:

  • 不清楚你想要什么逻辑。请用文字描述您想要的精确轮询逻辑。我也不清楚为什么你同时拥有setInterval()setTimeout()。当您尝试多次调用res.send() 时,会导致“发送后无法设置标头”的问题。此外,importStatus 是什么以及它与您的轮询逻辑有何关系。它没有在您显示的代码中定义或更改。
  • 在我看来,如果importStatus 不是true,那么你永远不会清除你的setInterval()。它只会一直运行下去,一旦 pollCount > 15,你会在间隔计时器的每个滴答声上继续做res.sendStatus(500)
  • 我想投票直到结果为真。但如果超过一定数量,则不要投票。这就是我想要实现的。 importStatus 是 db 调用的结果。它提供值是真还是假。我无法弄清楚如何清洁它。我实际上不想同时使用 settimeout 和 setInterval。抱歉,代码不好。
  • 在您显示的代码中 importStatus 未定义,并且与您显示的 sequelize.query() 结果没有任何关系。事实上,您不会对这段代码中的数据库结果做任何事情。所以,我不明白你投票的目的是什么?这真的是所有相关代码吗?或者,你遗漏了什么?
  • 仅供参考,至少,您可能在某处缺少clearInterval(processStatusCheck),因为如果importStatus 永远不会出现true,那么即使您已经完成@,您也永远不会停止间隔987654335@.

标签: javascript node.js asynchronous settimeout setinterval


【解决方案1】:

仍然没有遵循所需的逻辑,因为您还没有真正解释您期望它如何工作。我将描述你在做什么,并指出该流程中的几个缺陷。

  1. 您开始一个间隔,每 5 秒运行一次。
  2. 直到importStatus 变为true,但此循环中没有设置importStatus,因此它似乎永远不会满足。
  3. 您在循环内执行数据库查询,但甚至从未引用数据库查询的结果。我认为这不可能是正确的。同样,您发布的内容中一定缺少一些代码。
  4. 然后,在间隔 15 次迭代后,您还开始每 18 秒执行一次setTimeout()
  5. 因此,5 秒间隔和 18 秒setTimeout() 都在运行。
  6. 然后,在 15 次迭代后,您执行 res.sendStatus(500),但永远不要停止 setInterval(),它会一直运行并在每次触发时一直尝试执行 res.sendStatus(500)

问题总结:

  1. 此代码中的任何内容都不会对importStatus 进行任何操作,因此基于此代码它永远不会是true。我假设您的真实代码必须与您在此处显示的不同。
  2. 如果importStatus 永远不是true(参见上一点),那么您永远不会停止间隔——它会永远运行。您需要停止间隔计时器,可能在几个地方。当你做res.sendStatus(500)时当然要停止它,当你开始做setTimeout()时也可能停止它。
  3. 在间隔 15 次迭代后,您开始设置 setTimeout() 18 秒。所以,现在间隔和setTimeout() 都在运行。你似乎不太可能想要那样。当您开始执行setTimeout() 时,也许您应该停止setInterval()
  4. addProcess() 展示了一个异步风格的回调接口,但没有机会进行错误处理。真的是一个不会出错的函数吗?
  5. 您甚至从未引用数据库查询结果data,因此从未使用过该查询。

编辑您的评论:

这是我要实现的逻辑。 1) 每 10 秒轮询数据库 15 次。 2)即使在1分半钟后,如果状态不正确,发送500并停止进程。

嗯,15 次,每次 10 秒和 1-1/2 分钟并不是全部加起来的。 15 次,每次 10 秒为 150 秒,即 2-1/2 分钟。这是一个在 10 秒内执行 15 次的实现。您可以根据需要调整数字。

  let pollCount = 0;
  const processStatusCheck = setInterval(function statusCheck() {
    sequelize.query(dbQuery).then(function (data) {
       if (someCondition) {
            clearInterval(processStatusCheck);
            addProcess(Id, function (response) {
               res.send(200)
            });
       } else {
            ++pollCount;
            if (pollCount > 15) {
                clearInterval(processStatusCheck);
                res.sendStatus(500);
            }
       }
  }, 10 * 1000);

【讨论】:

  • 实际上没有,我隐藏了部分代码。 importStatus 值实际上是从 data 设置的。理想情况下,我想在 15 次迭代后停止轮询并退出整个函数。您对importStatus 的假设是正确的。 addProcess 在我的真实代码中有错误处理程序,为了避免这里出现大量代码,我已将其删除。这是我要实现@jfriend00 的逻辑 1) 每 10 秒轮询数据库 15 次。 2)即使在1分半钟后,如果状态不正确,发送500并停止进程。
  • @Kumar - 好吧,我在我的答案中添加了一个实现,它可以满足您在评论中添加的内容。
  • @Kumar - 如果这回答了您的问题,那么您可以通过单击答案左侧的复选标记向社区表明这一点。遵循正确的程序,这也将为您赢得一些声誉积分。
猜你喜欢
  • 2021-06-29
  • 2013-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多