7

well,

i'm completely new to node.js. Starting to try it, i'm following the introduction made by Ryan Dahl (http://www.youtube.com/watch?v=jo_B4LTHi3I) and at this point (around 0:17:00) there's an explanation about how server handles responses,

The basic example is to have a 'hello' output from webserver and then after 2 secs it comes the 'world', this code is supposed to do that

//Require the webserver library 
var http = require('http');

var server = http.createServer(function(req, res) {
    res.writeHead(200, { 'content-type' : 'text-plain' });
    res.write('Hello\n');

    //Asynchronous behavior
    setTimeout(function() {
        res.end('World\n');
    }, 2000);
});

server.listen(3000);

So i run it, and i get the Hello World but there's only one response from server with the complete result, that is, request > 2 sec > 'Hello World'. Instead of request > Hello > 2 secs > World.

Why is that?, How can i change this behaviour?

I'm using v0.8.18, curl -i http://localhost:3000 returns the right headers... HTTP/1.1 200 OK content-type: text-plain Date: Sat, 26 Jan 2013 18:10:05 GMT Connection: keep-alive Transfer-Encoding: chunked

jantimon
  • 36,840
  • 23
  • 122
  • 185
Alexander Fradiani
  • 1,001
  • 3
  • 13
  • 33
  • That is the idea of HTTP, the request gets sent if it is completed, which is after the 'World' is appended to the request, so after 2 seconds. – 11684 Jan 26 '13 at 18:51
  • I see... but that's what's not explained about how node is supposed to work. In fact you can see in the demonstration that the response is received in two parts. – Alexander Fradiani Jan 26 '13 at 18:56
  • people run into problems doing this with http across all kinds of programming langs, web servers, and clients. Something will buffer the output a tiny bit and destroy the progressive effect. Try padding the snot out of your strings with spaces, and try a different client. – goat Jan 26 '13 at 19:01
  • With curl, your code performs as expected. A browser waits for the whole body, but curl prints "hello", waits 2 seconds then prints "worls". I copied your exact code and it's ok. – randunel Jan 26 '13 at 19:04
  • @randunel you're right. I suppose i can mark that as an answer if you change it from comment. – Alexander Fradiani Jan 26 '13 at 19:10
  • you can simply delete the question if you want to. I added the meta-answer :D – randunel Jan 26 '13 at 19:12
  • @AlexanderFradiani My first comment was actually wrong, I'm sorry. Look at loganfsmyth's answer for an explanation. – 11684 Jan 26 '13 at 19:38

3 Answers3

6

It is the browser that buffers the incoming data until some amount has been received, before starting to render. Your Node code does just as you expect, it will sent the first part of the response, then wait for 2 seconds, then send the second half.

If you want to observe this behavior, you can send a bunch of spaces to make the browser empty its buffer. If you add this after your initial write, you will see the browser render the first half of the request.

var str = '';
for (var i = 0; i < 2000; i++){
  str += ' ';
}
res.write(str);

Obviously don't do this in real code, but it's good to demonstrate the behavior.

loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • @11684 No problem! Learning stuff is my favorite part of SO. – loganfsmyth Jan 26 '13 at 20:02
  • @loganfsmyth Do you know how Ryan Dahl originally solved the file upload progress bar problem with NodeJS. This answer makes sense... but you said you would never use this in production to send updates to the browser. More context to my question can be found here: http://stackoverflow.com/questions/31529013/nodejs-file-upload-with-progress-bar-using-core-nodejs-and-the-original-node-s – HelpMeStackOverflowMyOnlyHope Jul 21 '15 at 02:27
1

With curl, your code performs as expected. A browser waits for the whole body, but curl prints "hello", waits 2 seconds then prints "worls". I copied your exact code and it's ok.

randunel
  • 8,917
  • 1
  • 26
  • 24
0

you can change behavior using content type text/html

res.writeHead(200, { 'content-type' : 'text/html' });

the browser will act differently on different content-type. also using content-type text-html will make curl hold buffer and only print after buffer finished

i just test this on experiment, still i dont know why on browser and on curl doing like that