2017-10-19 25 views
-1

我想創建一個客戶可以查看其訂單狀態的實時訂購頁面。如果用戶斷開連接或符合條件,停止方法/間隔

因此,我想每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未定義,或者如果我在全局定義它,它會停止錯誤的功能。

這怎麼能正確完成?

+1

簡單地說,不要使用間隔來處理異步內容。如果這會延遲很多併發請求的運行。只需使用遞歸setTimeout –

回答

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. 我加了一個防範覆蓋checkInterval變量,如果你有機會的trackorder事件不止一次相同的客戶端。

  2. 你在一個地方拼錯了checkinterval

  3. 正如其他人所說,代表每個客戶端輪詢您的數據庫是一個壞的設計,不會擴展。你需要使用數據庫觸發器(所以它會告訴你什麼時候某些有趣的事情發生了變化),或者讓你自己的代碼對數據庫進行相關的更改會觸發更改。不要代表每個客戶進行投票。

  4. 您在pool.getConnection()connection.query()中沒有錯誤處理。

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); 
    }); 
})(); 
} 
+0

在這種情況下,如果用戶斷開連接,我將如何停止檢查? – maddo7

0

我會說你使用了一種不好的方法。你應該去而不是

我的意思是,當訂單狀態改變時發出事件。不要讓數據庫的負擔無緣無故地頻繁發生。

上的成功地位的變化,發出事件order_status_updateorder id,什麼是new status

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

這樣,你不需要任何形式的循環或setInterval的等別擔心,即使客戶端連接的或不,其sockat.io業務來照顧它。你只會提出這個事件。

相關問題