Search code examples
javascriptnode.jsexpresssocket.ioreal-time

How to continuously update random data from server to web client without must manually refresh browser?


I have random data from server and want to send it into web client without refresh the browser. I use web framework express.js with template engine pug.js, socket.io and jquery.

This is the code:

app.js

var express = require('express');
var socket_io = require('socket.io');
var app = express();
var io = socket_io();
app.io = io;

var randomNum = Math.random();
var randomNum2 = Math.random();

var data = [
   {
      random1: randomNum,
      random2: randomNum2
   }
]

io.on('connection', (socket) => {
   socket.emit('random', data);
});

module.exports = app;

routers/index.js

var express = require('express');
var router = express.Router();

router.get('/', function(req, res, next) {
    res.render('index');
});

module.exports = router;

views/layout.pug

doctype html
html
  head
    title= title
    script(src="//code.jquery.com/jquery-1.11.2.min.js")
    script(src="//code.jquery.com/jquery-migrate-1.2.1.min.js")
    script(src='js/socket.io.js')
  body
    block content
    script(type='text/javascript').
      $(document).ready(function() {
        var socket = io();

        socket.on('connect', onConnect);
        function onConnect() {
            console.log('socket connected');
        }

        socket.on('random', function(data) {
          for(var keys in data) {
            $('#random1').html(`<div>random1: ${data[keys].random1}</div>`);
            $('#random2').html(`<div>random2: ${data[keys].random2}</div>`);
          }
        });
      });

views/index.pug

extends layout

block content
  #random1
  #random2

With all code above, if i run express server then the variable randomNum automatically generate random number and send it using socket.emit to views/layout.pug and passing it to html div. It works fine but after that nothing changed.

Now i try to use setInterval 5 seconds in app.js

// app.js
...

setInterval(() => {
   var randomNum = Math.random();
   var randomNum2 = Math.random();

   var data = [
      {
         random1: randomNum,
         random2: randomNum2
      }
   ]
}, 5000);  

...

If i run express server and navigate to web browser, the random number automatically generated for the first time and after that i wait for almost 20 seconds and nothing changed. I must manually refresh the browser to get the value change.

Is there something wrong with setInterval or i put it in the wrong place?

Can someone help me to make the number change automatically without refresh the browser?

Thank you very much.

Edited

// app.js
...

setInterval(() => {
  var randomNum = Math.random();
  var randomNum2 = Math.random();

  var data = [
      {
          random1: randomNum,
          random2: randomNum2
      }
  ]

  io.on('connection', (socket) => {
      socket.emit('random', data);
  });
}, 5000);

...

Solution

  • you can't just change a different variable called data (different scope) and expect a function that is in callback to be executed as if javascript just "knows what you want to do"

    Though, your code is close

    I think you want something like this

    var express = require('express');
    var socket_io = require('socket.io');
    var app = express();
    var io = socket_io();
    app.io = io;
    
    var randomNum = Math.random();
    var randomNum2 = Math.random();
    
    var data = [
       {
          random1: randomNum,
          random2: randomNum2
       }
    ]
    
    io.on('connection', (socket) => {
       socket.emit('random', data); // on connection, everyone gets exactly the same global one-time random data
       setInterval(() => { // every 5 seconds, each client gets different random data
           var randomNum = Math.random();
           var randomNum2 = Math.random();
    
           var data = [
              {
                 random1: randomNum,
                 random2: randomNum2
              }
           ]
           socket.emit('random', data);
        }, 5000);  
    });
    module.exports = app;
    

    well, that's sucky code for sure ... unless you want everyone getting the same first random data

    const express = require('express');
    const socket_io = require('socket.io');
    const app = express();
    const io = socket_io();
    app.io = io;
    
    io.on('connection', socket => {
        const sendRandomData = () => {
            const random1 = Math.random();
            const random2 = Math.random();
    
            const data = [{random1,random2}];
            socket.emit('random', data);
        };
       sendRandomData();
       setInterval(sendRandomData, 5000);  
    });
    module.exports = app;