使用generator函数next()作为node.js中的回调

tya*_*apo 5 javascript yield node.js

我正在编写一些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);
}
Run Code Online (Sandbox Code Playgroud)

所以,我的顺序控制代码在一个生成器中,readSensor()当它需要读取时产生.传感器读取完成后,它会调用回调,然后控制返回主代码.我这样做是因为我可能需要根据之前的读数以不同的顺序读取各种传感器.所以,这是一个值得怀疑的部分:我this.next.bind(this)作为回调函数传递给异步读取函数.当启用生成器(--harmony_generators)时,代码似乎工作,但我想知道这里是否存在我遗漏的陷阱.我对JS比较新,所以不要害怕指出明显的:)

JLR*_*she 2

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

我建议修改或包装readSensor以返回承诺,然后使用本文中概述的技术。

这将允许您编写如下代码(已在 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);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

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

  • @Vadorequest 它表示一个[生成器函数](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*)。 (2认同)