【问题标题】:Stop method/interval if user disconnects or condition is met如果用户断开连接或满足条件,则停止方法/间隔
【发布时间】:2017-10-19 17:11:26
【问题描述】:

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

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

如何才能正确地做到这一点?

【问题讨论】:

  • 不要对异步的东西使用间隔。如果延迟太多,您就会有并发请求在运行。只需使用递归 setTimeout

标签: javascript node.js socket.io setinterval


【解决方案1】:

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

另外:

  1. 如果您曾多次为同一个客户端收到trackorder 事件,我添加了一个防止覆盖checkInterval 变量的保护措施。

  2. 您在一处拼错了checkinterval

  3. 正如其他人所说,代表每个客户端轮询您的数据库是一种糟糕的设计,并且无法扩展。您需要使用数据库触发器(这样当有趣的事情发生变化时它会告诉您)或拥有自己的代码来对数据库进行相关更改来触发更改。不要代表每个客户进行投票。

  4. 您在pool.getConnection()connection.query() 中都没有错误处理。

【讨论】:

    【解决方案2】:

    不用那么复杂的 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);
      });
     })();
    }
    

    【讨论】:

    • 在这种情况下,如果用户断开连接,我将如何停止检查?
    【解决方案3】:

    我会说你使用了一种糟糕的方法。你应该选择 push 而不是 pull

    我的意思是,当订单状态发生变化时发出事件。不要无缘无故地频繁访问数据库。

    成功更改状态后,使用order id 发出事件order_status_updatenew status 是什么

    socket.emit('order_status_update', {order_id: 57, status: 'In Process'});
    

    这样您就不需要任何类型的循环或 setinterval 等。即使客户端连接与否也不用担心,它的 sockat.io 业务来处理它。您只需提出该事件即可。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-26
      • 1970-01-01
      • 2020-12-27
      • 1970-01-01
      • 2021-07-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多