我试图在node.js中实现和现有的解决方案,特别是使用express.js框架。现在,现有解决方案的工作原理如下:
基本上发生的是,客户端连接并且连接处于活动状态(在循环中),直到有足够的客户端连接,然后才会有响应(同时对所有客户端)。
现在我不是这些架构的专家,但从我的想法来看,这不是一个正确或好的解决方案。我最初的想法是:这个必须用套接字来解决。但是,由于现有的解决方案就是这样(它不是用node.js编写的),我试图模仿这种行为:
var number = (function(){
var count = 0;
return {
increase: function() {
count++;
},
get: function(){
return count;
}
};
})();
app.get('/test', function(req, res){
number.increase();
while (number.get() < 3) {
//hold it here, until enough clients connect
}
res.json(number.get());
});
现在,当我认为这不是一个正确的解决方案时,我有几个问题:
答案 0 :(得分:3)
我可能会为此使用事件发射器:
var EventEmitter = require('events').EventEmitter;
var emitter = new EventEmitter();
app.get('/', function(req, res) {
// Increase the number
number.increase();
// Get the current value
var current = number.get();
// If it's less than 3, wait for the event emitter to trigger.
if (current < 3) {
return emitter.once('got3', function() {
return res.json(number.get());
});
}
// If it's exactly 3, emit the event so we wake up other listeners.
if (current === 3) {
emitter.emit('got3');
}
// Fall through.
return res.json(current);
});
我想强调的是@Plato在说明响应需要太多时间才能完成时,浏览器可能会超时。
编辑:另外,对return emitter.once(...)
的一些解释。
上面的代码可以这样重写:
if (current < 3) {
emitter.once('got3', function() {
res.json(number.get());
});
} else if (current === 3) {
emitter.emit('got3');
res.json(number.get());
} else {
res.json(number.get());
}
但是我没有使用那些if/else
语句,而是在创建事件监听器之后从请求处理程序返回。由于请求处理程序是异步的,因此它们的返回值将被丢弃,因此您可以返回任何内容(或任何内容)。作为替代方案,我也可以使用它:
if (current < 3) {
emitter.once(...);
return;
}
if (current === 3) {
...etc...
此外,即使您从请求处理程序函数返回,事件侦听器仍然引用res
变量,因此请求处理程序范围由Node维护,直到事件侦听器回调中的res.json()
为止。调用。
答案 1 :(得分:1)
process.nextTick()
执行此操作,但setTimeout()
也适用:var number = (function(){
var count = 0;
return {
increase: function() {
count++;
},
get: function(){
return count;
}
};
})();
function waitFor3(callback){
var n = number.get();
if(n < 3){
setImmediate(function(){
waitFor3(callback)
})
} else {
callback(n)
}
}
function bump(){
number.increase();
console.log('waiting');
waitFor3(function(){
console.log('done');
})
}
setInterval(bump, 2000);
/*
app.get('/test', function(req, res){
number.increase();
waitFor3(function(){
res.json(number.get());
})
});
*/