如果用户断开连接或满足条件,则停止方法/间隔

时间:2017-10-19 17:11:27

标签: javascript node.js socket.io setinterval

我想创建一个实时订单页面,客户可以在其中查看订单状态。

因此我想每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未定义或者如果我全局定义它会停止错误的函数。

如何正确完成?

3 个答案:

答案 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);
    });
});

另外:

  1. 如果您为同一个客户端多次获得checkInterval个事件,我会添加一个警告来覆盖trackorder变量。

  2. 您在一个地方误导了checkinterval

  3. 正如其他人所说,代表每个客户端轮询数据库是一个不好的设计,不会扩展。您需要使用数据库触发器(因此它会告诉您何时发生了有趣的更改)或者您自己的代码会对数据库进行相关更改会触发更改。不要代表每个客户进行投票。

  4. 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业务可以处理它。你只会举起这个活动。