【问题标题】:How to call a generator (async) function on an interval basis如何在间隔的基础上调用生成器(异步)函数
【发布时间】:2017-08-23 07:25:02
【问题描述】:

我正在构建一个应用程序,该应用程序必须每 2 秒轮询一次远程设备(生成器 fn sendRequests())。

使用 setInterval 调用生成器 fn 的正确方法是什么,它不是生成器,也不会产生

function * sendRequests() {
  // multiple remote async requests are sent
}

var timer = setInterval(() => {
  // yield sendRequests()
}, 2000)

【问题讨论】:

  • 为什么是生成器函数?最多不应该是async function 吗?您是否忘记将其包装在 co.wrap(或您正在使用的任何异步运行程序库)中?
  • 为了清楚起见,我将更新问题,但该函数是生成器。它在 AdonisJS 平台上使用生成器代替 Promise 和回调进行异步操作,并且还没有为 ES7 异步 fns 做好准备。在这种情况下,异步操作是一个远程 MODBUS/TCP 请求。

标签: javascript asynchronous setinterval adonis.js


【解决方案1】:

setInterval 回调中让出的问题是yield 只能让出给立即包含它的生成器function*。因此,您不能通过回调yield

你可以从回调中做的是解决一个 Promise,你的生成器函数可以yield

async function* pollGen() {
  yield new Promise((resolve, reject) => {
    setInterval(() => resolve(...), 2000);
  });

问题在于Promise can only be settled once。因此,每 2000 毫秒调用一次 resolve 将不会执行第一次调用之外的任何操作。

您可以做的是在 while 循环中反复调用 setTimeout

async function* pollGen() {
  let i = 0;
  while (i < 10)
    yield new Promise((resolve, reject) => {
      setTimeout(() => resolve(i++), 200);
    });
}

(async function main() {
  // for-await-of syntax
  for await (const result of pollGen())
    console.log(result);
}());

新的for-await-of 语法从 Node v9.2 开始可用,并且可以在 Node v10 或更高版本中使用,无需任何标志。

【讨论】:

  • 这可行,但只要未解决承诺,您的 while 循环基本上会阻止执行,这有点违背您的setTimeout 的目的。
【解决方案2】:

由于 AdonisJS 在底层使用 co(),我使用了 @Bergi 建议将 co() 包装起来

function * sendRequests() {
  // multiple remote async requests are sent
}

var timer = setInterval(() => {
  co(function * () {
    yield sendRequests()
  })
}, 2000)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-20
    • 2017-12-06
    • 1970-01-01
    • 2018-05-02
    • 1970-01-01
    • 2015-11-29
    • 1970-01-01
    相关资源
    最近更新 更多