如果用户断开连接或符合条件,停止方法/间隔
我想创建一个客户可以查看其订单状态的实时订购页面。如果用户断开连接或符合条件,停止方法/间隔
因此,我想每10秒运行一个函数,检查SQL数据库,如果订单已准备就绪。
function checkOrder(socket, userid, checkinterval) {
pool.getConnection(function(err, connection) {
// Use the connection
connection.query('SELECT * FROM orders WHERE user = ' + userid + ' ORDER BY timestamp DESC', function(err, rows) {
var alldone = false;
for (var i = 0; i < rows.length; i++) {
if (rows[i]['status'] == 'completed') {
alldone = true;
} else {
alldone = false;
break;
}
}
socket.emit('order-update', rows);
connection.release();
if (alldone) {
console.log('all done');
socket.emit('execute', '$("#orderstatus").html(\'Done\');');
clearInterval(checkinterval);
}
});
});
}
var express = require('express');
var app = express();
var app = express();
var options = {
key: fs.readFileSync('privkey.pem'),
cert: fs.readFileSync('cert.pem'),
ca: fs.readFileSync("chain.pem")
};
var server = require('https').createServer(options, app);
var io = require('socket.io')(server);
var port = 443;
server.listen(port, function() {
console.log('Server listening at port %d', port);
});
io.on('connection', function(socket) {
socket.on('trackorder', function(userid) {
var checkinterval = setInterval(function() {
checkOrder(socket, userid, checkinterval);
}, 10000);
});
socket.on('disconnect', function() {
clearInterval(checkinterval);
});
});
现在我遇到了停止该功能的问题,如果任务完成或客户端断开连接。
我怎么能做到这一点?我想clearInterval()
将在函数内部工作,因为它已通过,但on disconnect
事件处理程序存在问题。 checkinterval
未定义,或者如果我在全局定义它,它会停止错误的功能。
这怎么能正确完成?
当disconnect
事件发生时,您的checkInterval
变量超出范围。您需要将其定义提升到一个水平。
io.on('connection', function(socket) {
// checkInterval variable is declared at this scope so all event handlers can access it
var checkInterval;
socket.on('trackorder', function(userid) {
// make sure we never overwrite a checkInterval that is running
clearInterval(checkInterval);
checkInterval = setInterval(function() {
checkOrder(socket, userid, checkInterval);
}, 10000);
});
socket.on('disconnect', function() {
clearInterval(checkinterval);
});
});
另外:
我加了一个防范覆盖
checkInterval
变量,如果你有机会的trackorder
事件不止一次相同的客户端。你在一个地方拼错了
checkinterval
。正如其他人所说,代表每个客户端轮询您的数据库是一个坏的设计,不会扩展。你需要使用数据库触发器(所以它会告诉你什么时候某些有趣的事情发生了变化),或者让你自己的代码对数据库进行相关的更改会触发更改。不要代表每个客户进行投票。
您在
pool.getConnection()
或connection.query()
中没有错误处理。
而不是那复杂的setInterval的东西,只是添加一个小的IIFE,如果结果尚未在那里调用自己。一些伪代码:
function checkOrder(socket, userid){
//a variable pointing to the running timer
var timer;
//on error clear
socket.on("disconnect",()=>clearTimout(timer));
//a small IIFE
(function retry(){
pool.getConnection(function(err, connection) {
//parse & notice socket
if (!alldone) //retry
timer = setTimeout(retry, 1000);
});
})();
}
在这种情况下,如果用户断开连接,我将如何停止检查? – maddo7
我会说你使用了一种不好的方法。你应该去推而不是拉。
我的意思是,当订单状态改变时发出事件。不要让数据库的负担无缘无故地频繁发生。
上的成功地位的变化,发出事件order_status_update
与order id
,什么是new status
socket.emit('order_status_update', {order_id: 57, status: 'In Process'});
这样,你不需要任何形式的循环或setInterval的等别担心,即使客户端连接的或不,其sockat.io
业务来照顾它。你只会提出这个事件。
简单地说,不要使用间隔来处理异步内容。如果这会延迟很多并发请求的运行。只需使用递归setTimeout –