User is lazy, don’t want to wait for data and quit the page. How I can access router.post to stop further code execution?
APP.JS FILE (backend):
var express = require('express');
var expressSession = require('express-session');
var redis = require('redis');
var connectRedis = require('connect-redis');
var body_parser = require('body-parser');
var compression = require('compression');
var RedisStore = connectRedis(expressSession);
var io = require('socket.io');
var data = require('./routes/data.js');
var page = require('./routes/page.js');
var app = express();
app.use(compression());
app.set('view engine', 'ejs');
app.set('views', __dirname + '/pages');
app.use('/', data);
app.use('/page', page);
io.on('connection', function(socket){
socket.request.session; // session
socket.id; // id
soc.on('user-abort', function(id){
id.specificUser; // we need to close this connection and all the code that is synchronized with this id/socket
});
});
PAGE.JS FILE (router):
router.post('/page', function(req, res, next)
{
//we render page so we can send the proper data
res.render('page');
req.session // we get id here
var data = 'data';
// let suposse we send data to the user partialy:
function sendData(){
console.log("data");
setTimeout(sendData, 1000);
}
setTimeout(sendData, 1000);
// now user quit the page - how I can access router.post to stop the code execution ???
});
module.exports = router;
PAGE.EJS FILE (user side HTML):
window.onbeforeunload = function(e)
{
socket.emit('abort', {id : specificUser}, function(){
//user quit the page
});
};
2
Answers
For all intents and purposes, you can’t, at least not with the code that you’re showing.
The reason is that by using
res.render()
, you are causing the connection to the browser to get closed by your server, which means there is no way to detect if the user is quitting the page (well, you could try usingwindow.onunload
and sending special "user quit the page" request to your server, but a) that won’t be reliable and b) you’d have to match up that request to the particular timer that was started on behalf of that specific user).However, you are suggesting that your code would send additional data to the browser, which it doesn’t (because like I said,
res.render()
will close the connection when it’s done), so my guess is that your actual code looks differently, in which case it may be possible to detect the user from navigating away from the page.EDIT: I would suggest moving the "periodic update" code to the
socket.io
part of your app. The reason is that HTTP requests are ephemeral, and you’re basically starting a new timer for every request.If you’re adamant on running the updates from the request handler, I would probably use a global object to link session id’s (which are known to both the HTTP request handler and the
socket.io
handler) withsocket.io
connections, and store timer references and a boolean to reflect if the user has left the page.Something like this (very much untested):
But again, I would move
sendData
to thesocket.io
handler, I can see a whole lot of issues that may occur using the above code.If the "further code execution" that you want to prevent is asynchronous (for example, fetches data from a database), you can listen to the
close
event of the incoming request, if you send the HTML page withres.write
, withoutres.end
: