在NodeJS中发送HTTP响应之前等待事件发生?

我正在寻找一个解决scheme,在发送HTTP响应之前等待事件发生。

用例

  1. 这个想法是我在我的一个路由中调用一个函数: zwave.connect("/dev/ttyACM5"); 这个函数立即返回。
  2. 但是有两个事件会告诉你连接设备是成功还是失败:
 zwave.on('driver ready', function(){...}); zwave.on('driver failed', function(){...}); 
  1. 在我的路由中,我想知道在发送HTTP响应之前,设备是成功还是失败。

我的“解决scheme”

  1. 当事件发生时,我将事件保存在数据库中:
 zwave.on('driver ready', function(){ //In the database, save the fact the event happened, here it's event "CONNECTED" }); 
  1. 在我的路线中,执行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); }); });