我正在寻找在发送HTTP响应之前等待事件发生的解决方案。
使用案例
zwave.connect("/dev/ttyACM5");
此函数立即返回。zwave.on('driver ready', function(){...});
zwave.on('driver failed', function(){...});
我的解决方案"
zwave.on('driver ready', function(){
//In the database, save the fact the event happened, here it's event "CONNECTED"
});
router.get('/', function(request, response, next) {
zwave.connect("/dev/ttyACM5");
waitForEvent("CONNECTED", 5, null, function(){
response.redirect(/connected);
});
});
// The function use to wait for the event
waitForEvent: function(eventType, nbCallMax, nbCall, callback){
if(nbCall == null) nbCall = 1;
if(nbCallMax == null) nbCallMax = 1;
// Looking for event to happen (return true if event happened, false otherwise
event = findEventInDataBase(eventType);
if(event){
waitForEvent(eventType, nbCallMax, nbCall, callback);
}else{
setTimeout(waitForEvent(eventType, callback, nbCallMax, (nbCall+1)), 1500);
}
}
我认为这不是一个好习惯,因为它会迭代对数据库的调用。 那么您对此有何意见/建议?
答案 0 :(得分:8)
我已经开始将asynchronous和control-flow标记添加到您的问题中,因为在它的核心,这就是您要问的问题。 (另外,如果你不使用ES6,你应该能够将下面的代码翻译回ES5。)
有许多方法可以处理JavaScript中的异步控制流(另请参阅:What is the best control flow module for node.js?)。您正在寻找一种结构化的方式来处理它 - 可能是Promise
或Reactive Extensions for JavaScript (a.k.a RxJS)。
Promise
来自MDN:
Promise
对象用于异步计算。Promise
表示现在或将来可用或永不可用的值。
在您的情况下,异步计算是计算描述连接到设备成功或失败的布尔值。为此,您可以将connect
对象的调用封装在Promise
对象中,如下所示:
const p = new Promise((resolve) => {
// This assumes that the events are mutually exclusive
zwave.connect('/dev/ttyACM5');
zwave.on('driver ready', () => resolve(true));
zwave.on('driver failed', () => resolve(false));
});
一旦有Promise
表示连接状态,您就可以将功能附加到其未来"值:
// Inside your route file
const p = /* ... */;
router.get('/', function(request, response, next) {
p.then(successful => {
if (successful) {
response.redirect('/connected');
}
else {
response.redirect('/failure');
}
});
});
您可以详细了解Promises on MDN,或阅读有关该主题的众多其他资源之一(例如You're Missing the Point of Promises)。
答案 1 :(得分:3)
还有一个npm同步模块。用于同步执行查询的过程。
如果要以同步方式运行并行查询,则节点限制执行此操作,因为它永远不会等待响应。和同步模块非常适合这种解决方案。
示例代码
/*require sync module*/
var Sync = require('sync');
app.get('/',function(req,res,next){
story.find().exec(function(err,data){
var sync_function_data = find_user.sync(null, {name: "sanjeev"});
res.send({story:data,user:sync_function_data});
});
});
/*****sync function defined here *******/
function find_user(req_json, callback) {
process.nextTick(function () {
users.find(req_json,function (err,data)
{
if (!err) {
callback(null, data);
} else {
callback(null, err);
}
});
});
}
答案 2 :(得分:2)
zwave
可能已经实现了EventEmmiter,您只需要附加一个监听器
router.get('/', function(request, response, next) {
zwave.connect("/dev/ttyACM5");
zwave.once('driver ready', function(){
response.redirect(/connected);
});
});