我想创建一个实时订单页面,客户可以在其中查看订单状态。
因此我想每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
未定义或者如果我全局定义它会停止错误的函数。
如何正确完成?
答案 0 :(得分:1)
而不是那个复杂的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);
});
})();
}
答案 1 :(得分:1)
当checkInterval
事件发生时,您的disconnect
变量超出了范围。您需要将其定义提升一个级别。
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()
中没有错误处理。
答案 2 :(得分:0)
我会说你正在使用糟糕的方法。您应该选择推送而不是拉。
我的意思是,当订单状态发生变化时发出事件。不要无缘无故地将数据库负担放在数据库上。
成功更改状态后,使用order_status_update
发出事件order id
以及new status
socket.emit('order_status_update', {order_id: 57, status: 'In Process'});
通过这种方式,您不需要任何类型的循环或设置间隔等。即使客户端是否已连接也无需担心,其sockat.io
业务可以处理它。你只会举起这个活动。