我正在编写一些 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/