javascript - 在 node.js 中使用生成器函数 next() 作为回调

标签 javascript node.js yield

我正在编写一些 node.js 以通过串行端口连接与传感器交互。读取传感器的代码自然是异步的。不过,在我的控制代码中,我需要读取一个传感器,根据值做一些事情,再次读取,做一些其他事情等等。为此,我使用了类似以下独立测试的代码:

var main = new Main();
main.next();

function* Main()
{
  var reading = yield readSensor(this.next.bind(this));
  console.log(reading);

  var reading = yield readSensor(this.next.bind(this));
  console.log(reading);
}

function readSensor(callback)
{
  // simulate asynchrounous callback from reading sensor
  setTimeout(function sensorCallback() { callback('foo'); }, 100);
}

因此,我的顺序控制代码位于一个生成器中,该生成器在需要读取数据时生成 readSensor()。完成传感器读取后,它会调用回调,控制权会返回到主代码。我这样做是因为我可能需要根据以前的读数以不同的顺序读取各种传感器。所以,这是有问题的部分:我将 this.next.bind(this) 作为回调传递给异步读取函数。该代码似乎在启用生成器 (--harmony_generators) 时有效,但我想知道这里是否存在我遗漏的陷阱。我对 JS 比较陌生,所以不要害怕指出显而易见的地方:)

最佳答案

我没有深入研究 ES6 生成器,但让生成器将其自己的 .next 作为回调传递给另一个函数并不适合我。如果有的话,它可能会导致 readSensor 失败并且您无法处理失败,最终陷入死锁。

我建议修改或包装 readSensor 以返回 promise ,然后使用 this article 中概述的技术.

这将允许您编写这样的代码(已在 Node v0.12.0 中验证工作):

var Promise = require('q');

var main = async(function* () {
    var reading = yield readSensor();
    console.log(reading);

    reading = yield readSensor();
    console.log(reading);
});

main();

function readSensor() {
    return Promise.delay(2000).thenResolve(Math.random() * 100);
}



/***********************************************************
 * From here down,                                         *
 * boilerplate  async() function from article linked above *
 ***********************************************************/

function async(makeGenerator){
  return function () {
    var generator = makeGenerator.apply(this, arguments);

    function handle(result){
      // result => { done: [Boolean], value: [Object] }
      if (result.done) return Promise.resolve(result.value);

      return Promise.resolve(result.value).then(function (res){
        return handle(generator.next(res));
      }, function (err){
        return handle(generator.throw(err));
      });
    }

    try {
      return handle(generator.next());
    } catch (ex) {
      return Promise.reject(ex);
    }
  }
}

正如下面的 loganfsmyth 所指出的,Q 已经提供了一个 Q.async() 方法,它提供了这个 async() 函数的功能,并且可能其他 promise 库也这样做出色地。

关于javascript - 在 node.js 中使用生成器函数 next() 作为回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28973807/

相关文章:

c# - 嵌套产量在树中的表现

javascript - 测验 - if 语句

javascript - 将 element.parentProperty.childProperty 转换为数组语法

javascript - 如何捕获复选框输入

node.js - Mongoose 引用 _id 不起作用

python - 为什么这个 python 生成器每次都返回相同的值?

javascript - 避免类似协程的 JavaScript 函数中的 "yield"重复

javascript - 如何在 JavaScript 客户端截取网站/谷歌是如何做到的? (无需访问硬盘)

node.js - 无法使用 mocha 和 supertest 测试 DELETE 方法

javascript - 监听单个快速应用程序的 HTTP 和 HTTPS