XMLhttpRequest with a node js server with express

Problem

for a reason that i don't know i can't use the xmlhttprequest in my local server created in node js and express. Let me show you... Here is the server in node JS:

var 
express = require('express'),
app = express.createServer();

app.get('/count', function(req, res) {
    res.type('text/plain');
    res.write('Hello!')
     res.end();
});

app.listen(4003);

And it runs jus fine! when i acess localhost:4003/count i see "Hello!".

Now that the server is O.K, let's check the html page:

<script>

var xmlhttp = new XMLHttpRequest();
var resp = ""
xmlhttp.onreadystatechange = function() {
    if (xmlhttp.readyState==4 && xmlhttp.status==200){
        resp = xmlhttp.responseText;
        }
}

var cam = "localhost:4003/count"


function show(){
    xmlhttp.open("GET",cam,  true);
    xmlhttp.send();
    alert(resp);
}

</script>

<center><h1><div style="color:#339966"> <input type="button" value="Return of /count" onclick="javascript:show()"> </div> </h1>

So, it just don't work =[, i've already tried to:

  • change localhost:4003/count as value of the variable cam, for http://localhost:4003/count, 127.0.0.1:4003/count.
  • Open in Firefox, Safari and Chrome.
  • When i try to see the xmlhttp.status with an alert() it shows '0'. (but the page open normally in any browser)
Problem courtesy of: axius

Solution

Along with the timing issues that Morgan already covered...

  • When including a host in a URL, it needs to be prefixed by //.

    var cam = "//localhost:4003/count";
    

    Otherwise, it'll be treated as a relative path with localhost:4003 as a directory name.

  • You also have to deal with the Same-Origin Policy when using Ajax.

    So, if you're trying to use file:// for the page, this won't typically work well. The FILE protocol doesn't have an origin, so it can't pass the SOP, resulting in errors similar to:

    Origin null is not allowed by Access-Control-Allow-Origin.
    

    The easiest solution is to also serve the page from the application.

    You can do so either with a static() middleware.

    // `GET /` will serve `./public/index.html`
    app.use(express.static(__dirname + '/public'));
    

    Or with another route that sends the file itself.

    app.get('/', function (req, res) {
        res.sendfile(__dirname + '/public/index.html');
    });
    

    Then, access the page from:

    http://localhost:4003/
    
  • Also, with both the page and the count now served from the same origin, the URL can simply be relative-from-root:

    var cam = "/count";
    
Solution courtesy of: Jonathan Lonowski

Discussion

At the time you are trying to alert(resp) the resp variable hasn't been assigned, because onreadystatechange has not been called. If you moved the alert into onreadystatechange you should get the desired effect. This is also the point you could assign that value to an Element in the page.

Discussion courtesy of: Morgan ARR Allen

This recipe can be found in it's original form on Stack Over Flow.