在NodeJS中发送HTTP响应之前等待事件发生?
我正在寻找一个解决scheme,在发送HTTP响应之前等待事件发生。
用例
- 这个想法是我在我的一个路由中调用一个函数:
zwave.connect("/dev/ttyACM5");
这个函数立即返回。 - 但是有两个事件会告诉你连接设备是成功还是失败:
zwave.on('driver ready', function(){...}); zwave.on('driver failed', function(){...});
- 在我的路由中,我想知道在发送HTTP响应之前,设备是成功还是失败。
我的“解决scheme”
- 当事件发生时,我将事件保存在数据库中:
zwave.on('driver ready', function(){ //In the database, save the fact the event happened, here it's event "CONNECTED" });
- 在我的路线中,执行connect函数并等待事件出现在数据库中:
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); } }
我不认为这是一个很好的做法,因为它重复调用数据库。 那么你对此有什么意见/build议?
我已经提前,并添加asynchronous和控制stream标签到你的问题,因为在它的核心,这就是你问。 (另外,如果你不使用ES6,你应该可以把下面的代码翻译回ES5。)
TL; DR
有很多方法可以在JavaScript中处理asynchronous控制stream(另请参阅: 什么是node.js的最佳控制stream模块? )。 您正在寻找一种结构化的方式来处理它 – 可能是Promise
或JavaScript的Reactive Extensions(又名RxJS) 。
使用Promise
例子
来自MDN:
Promise
对象用于asynchronous计算。 一个Promise
是一个价值,可能现在,或将来,或从未。
在你的情况下的asynchronous计算是一个布尔值的计算,描述连接到设备的成功或失败。 要做到这一点,你可以包装呼叫来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'); } }); });
您可以在MDN上了解更多关于承诺的内容 ,或者通过阅读关于该主题的许多其他资源之一(例如, 您错过了承诺的要点 )。
还有一个npm同步模块。 用于同步执行查询的过程。
当你想以同步的方式运行并行查询时,节点限制就这么做,因为它永远不会等待响应。 同步模块对于这种解决scheme来说是非常完美的。
示例代码
/*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); } }); }); }
参考链接: https : //www.npmjs.com/package/sync
你尝试过吗? 从它的外观来看,你的zwave
可能已经实现了一个EventEmmiter ,你只需要附加一个监听器
router.get('/', function(request, response, next) { zwave.connect("/dev/ttyACM5"); zwave.once('driver ready', function(){ response.redirect(/connected); }); });