Question

I am having an issue with socket.io. I have a nodejs server that's acting as a webserver while also running a socket.io server. Additionally I have a webpage that connects to the socket.io server. The web page has one button that when clicked, emits a time update request. The socket.io server then sends back the time in milliseconds to the webpage which then updates a div to display the time.

This works fine, however, I've noticed that my web browser (Chrome) has the spinning loading icon in the tab and acts like the web page has never fully loaded. It also displays the 'X' to stop loading a page.

If I click the 'X' to stop loading the page, my software continues to work fine, but I cannot figure out why the page never completely loads.

Server Code:

var http = require("http");
var wrHandler = require("./webRequestHandler");
var io = require("socket.io");
var parser = require("./messageParser");

function start() {
    function onRequest(request, response){
        wrHandler.handle(request, response);        
    }

    var webserver = http.createServer(onRequest).listen(8888);
    console.log("Server has started.");



    var ioserver = io.listen(webserver);
    ioserver.set('log level', 3);
    ioserver.sockets.on('connection', function(socket){
        parser.parse(socket);
    });

}

exports.start = start;

Web Request Handler:

var url = require("url");
var fs = require("fs");

function handle(request, response){
    var pathname = url.parse(request.url).pathname;
    console.log(pathname);

        switch(pathname){
            case '/':
                fs.readFile("../html/index.html", function(error, data){
                    if(error){
                        response.writeHead(404);
                        response.write("This file does not exist.");
                    }
                    else{
                        response.writeHead(200, {"Content-Type": "text/html"});
                        response.write(data, "utf8");
                    }
                });
                break;
            default:
                fs.readFile("../html" + pathname, function(error, data){
                    if(error){
                        response.writeHead(404, {"Content-Type": "text/html"});
                        response.write("<html><body>This file does not exist!</body></html>");
                        console.log("Test");
                    }
                    else{
                        response.writeHead(200, {"Content-Type": "text/html"});
                        response.write(data, "utf8");
                    }
                });
        }
}

exports.handle = handle;

Message Parser:

function parseMessage(socket){
    socket.on('client_msg',function(data){
        var msgID = data.msgID;

        switch(msgID){
            case "gettime": 
                socket.emit('timeupdate', {"time": new Date().getTime()});
                break;
            default: break;
        }
    });
}

exports.parse = parseMessage;

HTML Page:

<html>
    <head>
        <script src="/socket.io/socket.io.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js"></script>
        <script>
            var socket = io.connect();

            function getTime(){
                socket.emit('client_msg', {"msgID": "gettime"});
            }

            socket.on('timeupdate', function(data){
                $("#time").text(data.time);
            });
        </script>
    </head>
    <body>

        <input type="button" value="Get Server Time" onclick="getTime()"/>
        <div id="time">

        </div>
    </body>
</html>

I should admit that I'm very new to node.js and not the strongest javascript developer either. Any criticism/advice/hints are greatly appreciated.

Was it helpful?

Solution

In your web request handler, at the end, do response.end() right outside of your switch block.

Edit: You have to do it at the end of each write, because you are doing asynchronous file reading. If you use readFileSync, you could write it once at the end.

http://nodejs.org/api/http.html#http_response_end_data_encoding

So your file would look like like:

    var url = require("url");
    var fs = require("fs");

    function handle(request, response){
        var pathname = url.parse(request.url).pathname;
        console.log(pathname);

            switch(pathname){
                case '/':
                    fs.readFile("../html/index.html", function(error, data){
                        if(error){
                            response.writeHead(404);
                            response.write("This file does not exist.");
                            response.end();
                        }
                        else{
                            response.writeHead(200, {"Content-Type": "text/html"});
                            response.write(data, "utf8");
                            response.end();
                        }
                    });
                    break;
                default:
                    fs.readFile("../html" + pathname, function(error, data){
                        if(error){
                            response.writeHead(404, {"Content-Type": "text/html"});
                            response.write("<html><body>This file does not exist!</body></html>");
                            response.end();
                            console.log("Test");
                        }
                        else{
                            response.writeHead(200, {"Content-Type": "text/html"});
                            response.write(data, "utf8");
                            response.end();
                        }
                    });
            }
    }

    exports.handle = handle;

Note that response.end('foo'); is equivalent to response.write('foo'); response.end();

Also, I know this is a bit off topic, but you should try out the express framework for node. It makes a lot of web request handling easy without being overly opinionated.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top