I have a problem with double emits when executing express (v4) route.
Lets for example run bellow code. Request (pipe) and mkdir will start immediately (race condition) and there will be error, about that the folder does not exist (mkdir can't create it fast enough, before request is started and start to pipe the data). Cause of this error user is redirected to page X where he need to refill the form. NOW (after redirection with form refilling) everything is working (cause folder do exist on the time that data arrives, because it was created before - cause async operations MUST complete? - route execute the code at the "back" even if user is already redirected) BUT the emits are done twice - once for OLD data, and once for NEW data (duplicating part of the HTML page structure).
route in x.js file:
router.post('/Y', function(req, res) {
request(opt, function(err, resp, body) {
if (resp.statusCode === 200) {
res.render('Y'); // so the emits can target something (they build html structure on page 'Y' with proper data)
function socCon()
{
var room = '';
return new Promise(function(resolve, reject)
{
req.io.on('connection', function(socket)
{
room = 'room-' + socket.id;
socket.join(room);
if (socket.join(room)) {
resolve(room);
}
else {
reject(console.log('error'));
}
});
});
}
socCon().then(data).catch(function(error)
{
console.log(error);
});
function data(room) {
var myFolder = 'myFolder/';
fs.mkdir(myFolder, {recursive : true}, function(err) {
if (err) {console.log(err);}
});
var file = fs.createWriteStream(myFolder + 'data.html', 'utf8');
sio.emit('msg', {emit : emit}); // socket.io emits - with use of express route POST on page 'X'
});
}
else {
res.render('X', {ERRORS : ERRORS});
res.end();
}
}).on('response', function(response) {
}).pipe(file).on('error', function(err) {
res.render('X', {ERRORS : ERRORS}); // we inform the user that he put wrong data in input field or that there is internal server error (whatever)
res.end();
// so we end 'Y' page connection here (but socket.io somehow collect all the data, emit it later on - when same route is hit again) and socket.sendBuffer does not work)
});
)};
Is there any way to stop the old emits? I have tried socket.sendBuffer = [];
(@jfreind00 suggestion at - socket.io stop re-emitting event after x seconds/first failed attempt to get a response) to no avail. Ideal would be to... stop whole request when there is redirection. But you can't stop async code from executing (or I just don't know how).
Client page Y:
<!DOCTYPE html>
<html>
<head>
<title>TITLE</title>
</head>
<body>
<script src="/socket.io/socket.io.js"></script>
<script type="text/javascript">
socket.on('connect', function() {
socket.sendBuffer = []; // does not work...
});
socket.on('msg', function(msg) {
// some HTML mutation here
});
</script>
</body>
</html>
Of course code is much more complicated, but this is enough (I think) to show the problem. This "application" is probably a bad design, but I don't know how to fix it.
index.js file (main "app" file):
var x = require('./routes/x.js');
var app = express();
app.use('/', x);
app.use(function(req, res, next) {
req.io = io;
next();
});
var io = require('socket.io')(server);
io.on('connection', function (soc) {
soc.on('disconnect', function(reason) {
console.log(reason);
});
// etc.
});