forked from manuelkiessling/nodebeginner.org
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index-en.html
3793 lines (3392 loc) · 239 KB
/
index-en.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>The Node Beginner Book » A comprehensive Node.js tutorial</title>
<meta name="description" content="A comprehensive Node.js tutorial for beginners: Learn how to build a full blown web application with server-side JavaScript" />
<link rel="icon" href="favicon.png" type="image/png" />
<link rel="stylesheet" type="text/css" href="default.css" />
</head>
<body>
<div id="forkmeongithub">
<a href="https://github.com/ManuelKiessling/NodeBeginnerBook"><img src="fork_me_on_github.png" width="149" height="149" alt="Fork me on GitHub" /></a>
</div>
<div id="ibookstore-banner">
<a href="buy-ibook/index.html"><img src="ibookstore-banner.jpg" width="100%" /></a>
</div>
<div id="translations">
<table>
<tr>
<td>
<a href="index-jp.html">
<div class="flag"><img src="jp-flag.png" width="24" height="24" alt="japanese flag" /></div>
<div class="text">日本語で読む</div>
</a>
</td>
<td>
<a href="index-es.html">
<div class="flag"><img src="es-flag.png" width="24" height="24" alt="spanish flag" /></div>
<div class="text">Lee este tutorial en Español</div>
</a>
</td>
<td>
<a href="index-kr.html">
<div class="flag"><img src="kr-flag.png" width="24" height="24" alt="korean flag" /></div>
<div class="text">이 튜토리얼을 한글로 보세요</div>
</a>
</td>
</tr>
<tr>
<td>
<a href="index-zh-cn.html">
<div class="flag"><img src="cn-flag.png" width="24" height="24" alt="chinese flag" /></div>
<div class="text">阅读本书中文版</div>
</a>
</td>
<td>
<a href="index-zh-tw.html">
<div class="flag"><img src="tw-flag.png" width="24" height="24" alt="traditional chinese flag" /></div>
<div class="text">閱讀本書繁體中文版</div>
</a>
</td>
<td>
<a href="http://www.nodebeginner.ru">
<div class="flag"><img src="ru-flag.png" width="24" height="24" alt="russian flag" /></div>
<div class="text">Читать этот учебник на русском</div>
</a>
</td>
</tr>
</table>
</div>
<div class="buybox">
<div class="buy-the-bundle">
<div class="cover">
<p>
The perfect introduction plus the perfect reference in one bundle!
</p>
<a href="buy-bundle/index.html"><img src="the_node_beginner_book_cover_small.png" height="86" width="57" /></a>
<a href="buy-bundle/index.html"><img src="hands-on_node.js_cover.png" height="86" width="57" /></a>
</div>
<div class="description">
<p>
LeanBundle currently offers<br />
the final version of
<br />
<strong>The Node Beginner Book</strong>
<br />
plus Pedro Teixeira's excellent
<br />
<strong>Hands-on Node.js</strong> for only
<br />
<br />
<strong class="price dollarsign">$</strong><strong class="price">9.99</strong>
<br />
(regular price <del>$21.98</del>)
</p>
</div>
<div class="buy">
<p>
226 pages in total
<br />
PDF, ePub & MOBI
<br />
Direct download
<br />
Free updates
</p>
<a class="buttonlink" href="buy-bundle/index.html">
<div class="button">Buy this<br />bundle now</div>
</a>
</div>
</div>
</div>
<div id="book">
<div>
<h1>The Node Beginner Book</h1>
<div id="author">A Node.js tutorial by <a href="http://twitter.com/manuelkiessling">Manuel Kiessling</a></div>
<a name="about"></a>
<h2>About</h2>
<p>
The aim of this document is to get you started with developing
applications with Node.js, teaching you everything you need to
know about "advanced" JavaScript along the way. It goes way
beyond your typical "Hello World" tutorial.
</p>
<a name="status"></a>
<h3>Status</h3>
<p>
You are reading the final version of this book, i.e., updates
are only done to correct errors or to reflect changes in new
versions of Node.js. It was last updated on September 9, 2012.
</p>
<p>
The code samples in this book are tested to work with Node.js
version 0.8.8.
</p>
<a name="intended-audience"></a>
<h3>Intended audience</h3>
<p>
This document will probably fit best for readers that have a
background similar to my own: experienced with at least one
object-oriented language like Ruby, Python, PHP or Java, only little
experience with JavaScript, and completely new to Node.js.
</p>
<p>
Aiming at developers that already have experience with other
programming languages means that this document won't cover
really basic stuff like data types, variables, control structures
and the likes. You already need to know about these to understand
this document.
</p>
<p>
However, because functions and objects in JavaScript are different
from their counterparts in most other languages, these will be
explained in more detail.
</p>
<a name="structure"></a>
<h3>Structure of this document</h3>
<p>
Upon finishing this document, you will have created a complete web
application which allows the users of this application to view web
pages and upload files.
</p>
<p>
Which, of course, is not exactly
world-changing, but we will go some extra miles and not only create
the code that is "just enough" to make these use cases possible,
but create a simple, yet complete framework to cleanly separate the
different aspects of our application. You will see what I mean in a
minute.
</p>
<p>
We will start with looking at how JavaScript development in Node.js
is different from JavaScript development in a browser.
</p>
<p>
Next, we will stay with the good old tradition of writing a "Hello
World" application, which is a most basic Node.js application that
"does" something.
</p>
<p>
Then, we will discuss what kind of "real" application we want to
build, dissect the different parts which need to be implemented to
assemble this application, and start working on each of these parts
step-by-step.
</p>
<p>
As promised, along the way we will learn about some of the more
advanced concepts of JavaScript, how to make use of them, and
look at why it makes sense to use these concepts instead of
those we know from other programming languages.
</p>
<p>
The source code of the finished application is available through
<a href="https://github.com/ManuelKiessling/NodeBeginnerBook/tree/master/code/application">the
NodeBeginnerBook Github repository</a>.
</p>
<div id="table-of-contents-headline">Table of contents</div>
<div id="table-of-contents">
<ul>
<li><a href="#about">About</a>
<ul>
<li><a href="#status">Status</a></li>
<li><a href="#intended-audience">Intended audience</a></li>
<li><a href="#structure">Structure of this document</a></li>
</ul>
</li>
<li><a href="#javascript-and-nodejs">JavaScript and Node.js</a>
<ul>
<li><a href="#javascript-and-you">JavaScript and You</a></li>
<li><a href="#a-word-of-warning">A word of warning</a></li>
<li><a href="#server-side-javascript">Server-side JavaScript</a></li>
<li><a href="#hello-world">"Hello World"</a></li>
</ul>
</li>
<li><a href="#a-full-blown-web-application-with-nodejs">A full blown web application with Node.js</a>
<ul>
<li><a href="#the-use-cases">The use cases</a></li>
<li><a href="#the-application-stack">The application stack</a></li>
</ul>
</li>
<li><a href="#building-the-application-stack">Building the application stack</a>
<ul>
<li><a href="#a-basic-http-server">A basic HTTP server</a></li>
<li><a href="#analyzing-our-http-server">Analyzing our HTTP server</a></li>
<li><a href="#passing-functions-around">Passing functions around</a></li>
<li><a href="#how-function-passing-makes-our-http-server-work">How function passing makes our
HTTP server work</a></li>
<li><a href="#event-driven-callbacks">Event-driven asynchronous callbacks</a></li>
<li><a href="#how-our-server-handles-requests">How our server handles requests</a></li>
<li><a href="#finding-a-place-for-our-server-module">Finding a place for our server module</a>
</li>
<li><a href="#whats-needed-to-route-requests">What's needed to "route" requests?</a></li>
<li><a href="#execution-in-the-kongdom-of-verbs">Execution in the kingdom of verbs</a></li>
<li><a href="#routing-to-real-request-handlers">Routing to real request handlers</a></li>
<li><a href="#making-the-request-handlers-respond">Making the request handlers respond</a>
<ul>
<li><a href="#how-to-not-do-it">How to not do it</a></li>
<li><a href="#blocking-and-non-blocking">Blocking and non-blocking</a></li>
<li><a href="#responding-request-handlers-with-non-blocking-operations">Responding
request handlers with non-blocking operations</a>
</li>
</ul>
</li>
<li><a href="#serving-something-useful">Serving something useful</a>
<ul>
<li><a href="#handling-post-requests">Handling POST requests</a></li>
<li><a href="#handling-file-uploads">Handling file uploads</a></li>
</ul>
</li>
<li><a href="#conclusion-and-outlook">Conclusion and outlook</a></li>
</ul>
</li>
</ul>
</div>
<a name="javascript-and-nodejs"></a>
<h2>JavaScript and Node.js</h2>
<a name="javascript-and-you"></a>
<h3>JavaScript and You</h3>
<p>
Before we talk about all the technical stuff, let's take a
moment and talk about you and your relationship with
JavaScript. This chapter is here to allow you to estimate
if reading this document any further makes sense for you.
</p>
<p>
If you are like me, you started with HTML "development"
long ago, by writing HTML documents. You came along this
funny thing called JavaScript, but you only used it in a
very basic way, adding interactivity to your web pages
every now and then.
</p>
<p>
What you really wanted was "the real thing", you wanted to
know how to build complex web sites - you learned a
programming language like PHP, Ruby, Java, and started
writing "backend" code.
</p>
<p>
Nevertheless, you kept an eye on JavaScript, you saw that
with the introduction of jQuery, Prototype and the likes,
things got more advanced in JavaScript land, and that this
language really was about more than <em>window.open()</em>.
</p>
<p>
However, this was all still frontend stuff, and although it
was nice to have jQuery at your disposal whenever you felt
like spicing up a web page, at the end of the day you were,
at best, a JavaScript <em>user</em>, but not a JavaScript
<em>developer</em>.
</p>
<p>
And then came Node.js. JavaScript on the server, how cool
is that?
</p>
<p>
You decided that it's about time to check out the old, new
JavaScript. But wait, writing Node.js applications is
one thing; understanding why they need to be written the
way they are written means - understanding JavaScript.
And this time for real.
</p>
<p>
Here is the problem: Because JavaScript really lives two,
maybe even three lives (the funny little DHTML helper from
the mid-90's, the more serious frontend stuff like jQuery
and the likes, and now server-side), it's not that easy to
find information that helps you to learn JavaScript the
"right" way, in order to write Node.js applications in a
fashion that makes you feel you are not just using
JavaScript, you are actually developing it.
</p>
<p>
Because that's the catch: you already are an experienced
developer, you don't want to learn a new technique by just
hacking around and mis-using it; you want to be sure that
you are approaching it from the right angle.
</p>
<p>
There is, of course, excellent documentation out there.
But documentation alone sometimes isn't enough. What is
needed is guidance.
</p>
<p>
My goal is to provide a guide for you.
</p>
<a name="a-word-of-warning"></a>
<h3>A word of warning</h3>
<p>
There are some really excellent JavaScript people out
there. I'm not one of them.
</p>
<p>
I'm really just the guy I talked about in the previous
paragraph. I know a thing or two about developing backend
web applications, but I'm still new to "real" JavaScript
and still new to Node.js. I learned some of the more
advanced aspects of JavaScript just recently.
I'm not experienced.
</p>
<p>
Which is why this is no "from novice to expert" book. It's
more like "from novice to advanced novice".
</p>
<p>
If I don't fail, then this will be the kind of
document I wish I had when starting with Node.js.
</p>
<a name="server-side-javascript"></a>
<h3>Server-side JavaScript</h3>
<p>
The first incarnations of JavaScript lived in browsers.
But this is just the context. It defines what you can
do with the language, but it doesn't say much about what
the language itself can do. JavaScript is a "complete"
language: you can use it in many contexts and achieve
everything with it you can achieve with any other
"complete" language.
</p>
<p>
Node.js really is just another context: it allows you to run
JavaScript code in the backend, outside a browser.
</p>
<p>
In order to execute the JavaScript you intend to run in the
backend, it needs to be interpreted and, well, executed.
This is what Node.js does, by making use of Google's V8 VM, the
same runtime environment for JavaScript that Google
Chrome uses.
</p>
<p>
Plus, Node.js ships with a lot of useful modules, so you don't
have to write everything from scratch, like for example
something that outputs a string on the console.
</p>
<p>
Thus, Node.js is really two things: a runtime environment and a
library.
</p>
<p>
In order to make use of these, you need to install Node.js.
Instead of repeating the process here, I kindly ask you to
visit
<a href="https://github.com/joyent/node/wiki/Installation" title="Building and Installing Node.js">the
official
installation instructions</a>. Please come back once you
are up and running.
</p>
<a name="hello-world"></a>
<h3>"Hello World"</h3>
<p>
Ok, let's just jump in the cold water and write our first
Node.js application: "Hello World".
</p>
<p>
Open your favorite editor and create a file called
<em>helloworld.js</em>. We want it to write "Hello World"
to STDOUT, and here is the code needed to do that:
</p>
<pre class="prettyprint lang-js"><span class="pln">console</span><span class="pun">.</span><span
class="pln">log</span><span class="pun">(</span><span class="str">"Hello World"</span><span class="pun">);</span></pre>
<p>
Save the file, and execute it through Node.js:
</p>
<pre>node helloworld.js</pre>
<p>
This should output <em>Hello World</em> on your terminal.
</p>
<p>
Ok, this stuff is boring, right? Let's write some real
stuff.
</p>
<a name="a-full-blown-web-application-with-nodejs"></a>
<h2>A full blown web application with Node.js</h2>
<a name="the-use-cases"></a>
<h3>The use cases</h3>
<p>
Let's keep it simple, but realistic:
</p>
<ul>
<li>
The user should be able to use our application with
a web browser
</li>
<li>
The user should see a welcome page when
requesting http://<em>domain</em>/start which displays a
file upload form
</li>
<li>
By choosing an image file to upload and submitting the
form, this image should then be uploaded to
http://<em>domain</em>/upload, where it is displayed once
the upload is finished
</li>
</ul>
<p>
Fair enough. Now, you could achieve this goal by googling
and hacking together <em>something</em>. But that's not
what we want to do here.
</p>
<p>
Furthermore, we don't want to write only the most basic
code to achieve the goal, however elegant and correct this code
might be. We will intentionally add more abstraction than
necessary in order to get a feeling for building more
complex Node.js applications.
</p>
<a name="the-application-stack"></a>
<h3>The application stack</h3>
<p>
Let's dissect our application. Which parts need to be
implemented in order to fulfill the use cases?
</p>
<ul>
<li>
We want to serve web pages, therefore we need an
<strong>HTTP server</strong>
</li>
<li>
Our server will need to answer differently to
requests, depending on which URL the request was
asking for, thus we need some kind of
<strong>router</strong> in order to map requests
to request handlers
</li>
<li>
To fulfill the requests that arrived at the server
and have been routed using the router, we need
actual <strong>request handlers</strong>
</li>
<li>
The router probably should also treat any incoming
POST data and give it to the request handlers in
a convenient form, thus we need <strong>request
data handling</strong>
</li>
<li>
We not only want to handle requests for URLs, we
also want to display content when these URLs are
requested, which means we need some kind of
<strong>view logic</strong> the request handlers
can use in order to send content to the user's
browser
</li>
<li>
Last but not least, the user will be able to upload
images, so we are going to need some kind of
<strong>upload handling</strong> which takes care of
the details
</li>
</ul>
<p>
Let's think a moment about how we would build this stack
with PHP. It's not exactly a secret that the typical setup
would be an Apache HTTP server with mod_php5 installed.
<br>
Which in turn means that the whole "we need to be able to
serve web pages and receive HTTP requests" stuff doesn't
happen within PHP itself.
</p>
<p>
Well, with node, things are a bit different. Because with
Node.js, we not only implement our application, we also
implement the whole HTTP server. In fact, our web
application and its web server are basically the same.
</p>
<p>
This might sound like a lot of work, but we will see in a
moment that with Node.js, it's not.
</p>
<p>
Let's just start at the beginning and implement the first
part of our stack, the HTTP server.
</p>
<a name="building-the-application-stack"></a>
<h2>Building the application stack</h2>
<a name="a-basic-http-server"></a>
<h3>A basic HTTP server</h3>
<p>
When I arrived at the point where I wanted to start with my
first "real" Node.js application, I wondered not only how to
actually code it, but also how to organize my code.
<br>
Do I need to have everything in one file? Most tutorials on
the web that teach you how to write a basic HTTP server in
Node.js have all the logic in one place. What if I want to
make sure that my code stays readable the more stuff I
implement?
</p>
<p>
Turns out, it's relatively easy to keep the different
concerns of your code separated, by putting them in
modules.
</p>
<p>
This allows you to have a clean main file, which you
execute with Node.js, and clean modules that can be used by
the main file and among each other.
</p>
<p>
So, let's create a main file which we use to start our
application, and a module file where our HTTP server code
lives.
</p>
<p>
My impression is that it's more or less a standard to name
your main file <em>index.js</em>. It makes sense to put our
server module into a file named <em>server.js</em>.
</p>
<p>
Let's start with the server module. Create the file
<em>server.js</em> in the root directory of your project,
and fill it with the following code:
</p>
<pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
class="str">"http"</span><span class="pun">);</span><span class="pln"><br><br>http</span><span
class="pun">.</span><span class="pln">createServer</span><span class="pun">(</span><span class="kwd">function</span><span
class="pun">(</span><span class="pln">request</span><span class="pun">,</span><span class="pln"> response</span><span
class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br> response</span><span
class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
class="pln"> </span><span class="str">"text/plain"</span><span class="pun">});</span><span
class="pln"><br> response</span><span class="pun">.</span><span class="pln">write</span><span
class="pun">(</span><span class="str">"Hello World"</span><span class="pun">);</span><span
class="pln"><br> response</span><span class="pun">.</span><span class="pln">end</span><span
class="pun">();</span><span class="pln"><br></span><span class="pun">}).</span><span
class="pln">listen</span><span class="pun">(</span><span class="lit">8888</span><span
class="pun">);</span></pre>
<p>
That's it! You just wrote a working HTTP server. Let's
prove it by running and testing it. First, execute your
script with Node.js:
</p>
<pre>node server.js</pre>
<p>
Now, open your browser and point it at
<a href="http://localhost:8888/" rel="nofollow">http://localhost:8888/</a>.
This should display a web page that says "Hello World".
</p>
<p>
That's quite interesting, isn't it. How about talking about
what's going on here and leaving the question of how to
organize our project for later? I promise we'll get back to
it.
</p>
<a name="analyzing-our-http-server"></a>
<h3>Analyzing our HTTP server</h3>
<p>
Well, then, let's analyze what's actually going on here.
</p>
<p>
The first line <em>require</em>s the <em>http</em> module
that ships with Node.js and makes it accessible through the
variable <em>http</em>.
</p>
<p>
We then call one of the functions the http module offers:
<em>createServer</em>. This function returns an object, and
this object has a method named <em>listen</em>, and takes
a numeric value which indicates the port number our HTTP
server is going to listen on.
</p>
<p>
Please ignore for a second the function definition that
follows the opening bracket of <em>http.createServer</em>.
</p>
<p>
We could have written the code that starts our server and
makes it listen at port 8888 like this:
</p>
<pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
class="str">"http"</span><span class="pun">);</span><span class="pln"><br><br></span><span class="kwd">var</span><span
class="pln"> server </span><span class="pun">=</span><span class="pln"> http</span><span
class="pun">.</span><span class="pln">createServer</span><span class="pun">();</span><span
class="pln"><br>server</span><span class="pun">.</span><span class="pln">listen</span><span class="pun">(</span><span
class="lit">8888</span><span class="pun">);</span></pre>
<p>
That would start an HTTP server listening at port 8888
and doing nothing else (not even answering any incoming
requests).
</p>
<p>
The really interesting (and, if your background is a more
conservative language like PHP, odd looking) part is the
function definition right there where you would expect the
first parameter of the <em>createServer()</em> call.
</p>
<p>
Turns out, this function definition IS the first (and only)
parameter we are giving to the <em>createServer()</em>
call. Because in JavaScript, functions can be passed around
like any other value.
</p>
<a name="passing-functions-around"></a>
<h3>Passing functions around</h3>
<p>
You can, for example, do something like this:
</p>
<pre class="prettyprint lang-js"><span class="kwd">function</span><span class="pln"> say</span><span
class="pun">(</span><span class="pln">word</span><span class="pun">)</span><span
class="pln"> </span><span class="pun">{</span><span class="pln"><br> console</span><span
class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span
class="pln">word</span><span class="pun">);</span><span class="pln"><br></span><span
class="pun">}</span><span class="pln"><br><br></span><span class="kwd">function</span><span class="pln"> execute</span><span
class="pun">(</span><span class="pln">someFunction</span><span class="pun">,</span><span class="pln"> value</span><span
class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br> someFunction</span><span
class="pun">(</span><span class="pln">value</span><span class="pun">);</span><span
class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>execute</span><span
class="pun">(</span><span class="pln">say</span><span class="pun">,</span><span
class="pln"> </span><span class="str">"Hello"</span><span class="pun">);</span></pre>
<p>
Read this carefully! What we are doing here is, we pass the
function <em>say</em> as the first parameter to the
<em>execute</em> function. Not the return value of
<em>say</em>, but <em>say</em> itself!
</p>
<p>
Thus, <em>say</em> becomes the local variable
<em>someFunction</em> within <em>execute</em>, and execute
can call the function in this variable by issuing
<em>someFunction()</em> (adding brackets).
</p>
<p>
Of course, because <em>say</em> takes one parameter,
<em>execute</em> can pass such a parameter when calling
<em>someFunction</em>.
</p>
<p>
We can, as we just did, pass a function as a parameter to
another function by its name. But we don't have to take this
indirection of first defining, then passing it - we can
define and pass a function as a parameter to another
function in-place:
</p>
<pre class="prettyprint lang-js"><span class="kwd">function</span><span class="pln"> execute</span><span
class="pun">(</span><span class="pln">someFunction</span><span class="pun">,</span><span class="pln"> value</span><span
class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br> someFunction</span><span
class="pun">(</span><span class="pln">value</span><span class="pun">);</span><span
class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>execute</span><span
class="pun">(</span><span class="kwd">function</span><span class="pun">(</span><span
class="pln">word</span><span class="pun">){</span><span class="pln"> console</span><span
class="pun">.</span><span class="pln">log</span><span class="pun">(</span><span
class="pln">word</span><span class="pun">)</span><span class="pln"> </span><span
class="pun">},</span><span class="pln"> </span><span class="str">"Hello"</span><span
class="pun">);</span></pre>
<p>
We define the function we want to pass to <em>execute</em>
right there at the place where <em>execute</em> expects its
first parameter.
</p>
<p>
This way, we don't even need to give the function a name,
which is why this is called an <em>anonymous function</em>.
</p>
<p>
This is a first glimpse at what I like to call "advanced"
JavaScript, but let's take it step by step. For now, let's
just accept that in JavaScript, we can pass a function as
a parameter when calling another function. We can do this
by assigning our function to a variable, which we then
pass, or by defining the function to pass in-place.
</p>
<a name="how-function-passing-makes-our-http-server-work"></a>
<h3>How function passing makes our HTTP server work</h3>
<p>
With this knowledge, let's get back to our minimalistic
HTTP server:
</p>
<pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
class="str">"http"</span><span class="pun">);</span><span class="pln"><br><br>http</span><span
class="pun">.</span><span class="pln">createServer</span><span class="pun">(</span><span class="kwd">function</span><span
class="pun">(</span><span class="pln">request</span><span class="pun">,</span><span class="pln"> response</span><span
class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br> response</span><span
class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
class="pln"> </span><span class="str">"text/plain"</span><span class="pun">});</span><span
class="pln"><br> response</span><span class="pun">.</span><span class="pln">write</span><span
class="pun">(</span><span class="str">"Hello World"</span><span class="pun">);</span><span
class="pln"><br> response</span><span class="pun">.</span><span class="pln">end</span><span
class="pun">();</span><span class="pln"><br></span><span class="pun">}).</span><span
class="pln">listen</span><span class="pun">(</span><span class="lit">8888</span><span
class="pun">);</span></pre>
<p>
By now it should be clear what we are actually doing here:
we pass the <em>createServer</em> function an anonymous
function.
</p>
<p>
We could achieve the same by refactoring our code to:
</p>
<pre class="prettyprint lang-js"><span class="kwd">var</span><span class="pln"> http </span><span
class="pun">=</span><span class="pln"> require</span><span class="pun">(</span><span
class="str">"http"</span><span class="pun">);</span><span class="pln"><br><br></span><span class="kwd">function</span><span
class="pln"> onRequest</span><span class="pun">(</span><span class="pln">request</span><span
class="pun">,</span><span class="pln"> response</span><span class="pun">)</span><span
class="pln"> </span><span class="pun">{</span><span class="pln"><br> response</span><span
class="pun">.</span><span class="pln">writeHead</span><span class="pun">(</span><span
class="lit">200</span><span class="pun">,</span><span class="pln"> </span><span
class="pun">{</span><span class="str">"Content-Type"</span><span class="pun">:</span><span
class="pln"> </span><span class="str">"text/plain"</span><span class="pun">});</span><span
class="pln"><br> response</span><span class="pun">.</span><span class="pln">write</span><span
class="pun">(</span><span class="str">"Hello World"</span><span class="pun">);</span><span
class="pln"><br> response</span><span class="pun">.</span><span class="pln">end</span><span
class="pun">();</span><span class="pln"><br></span><span class="pun">}</span><span class="pln"><br><br>http</span><span
class="pun">.</span><span class="pln">createServer</span><span class="pun">(</span><span class="pln">onRequest</span><span
class="pun">).</span><span class="pln">listen</span><span class="pun">(</span><span
class="lit">8888</span><span class="pun">);</span></pre>
<p>
Maybe now is a good moment to ask: Why are we doing it
that way?
</p>
<a name="event-driven-callbacks"></a>
<h3>Event-driven asynchronous callbacks</h3>
<p>
To understand why Node.js applications have to be written this way,
we need to understand how Node.js executes our code. Node's
approach isn't unique, but the underlying execution model is
different from runtime environments like Python, Ruby, PHP or Java.
</p>
<p>
Let's take a very simple piece of code like this:
</p>
<pre class="prettyprint lang-js">var result = database.query("SELECT * FROM hugetable");
console.log("Hello World");</pre>
<p>
Please ignore for now that we haven't actually talked about
connecting to databases before - it's just an example. The
first line queries a database for lots of rows, the second
line puts "Hello World" to the console.
</p>
<p>
Let's assume that the database query is really slow, that it has
to read an awful lot of rows, which takes several seconds.
</p>
<p>
The way we have written this code, the JavaScript interpreter of
Node.js first has to read the complete result set from the
database, and then it can execute the <em>console.log()</em>
function.
</p>
<p>
If this piece of code actually was, say, PHP, it would work the
same way: read all the results at once, then execute the next line
of code. If this code would be part of a web page script, the user
would have to wait several seconds for the page to load.
</p>
<p>
However, in the execution model of PHP, this would not become a
"global" problem: the web server starts its own PHP process for
every HTTP request it receives. If one of these requests results
in the execution of a slow piece of code, it results in a slow
page load for this particular user, but other users requesting
other pages would not be affected.
</p>
<p>
The execution model of Node.js is different - there is only one
single process. If there is a slow database query somewhere in
this process, this affects the whole process - everything comes
to a halt until the slow query has finished.
</p>
<p>
To avoid this, JavaScript, and therefore Node.js, introduces the
concept of event-driven, asynchronous callbacks, by utilizing an
event loop.
</p>
<p>
We can understand this concept by analyzing a rewritten version
of our problematic code:
</p>
<pre class="prettyprint lang-js">database.query("SELECT * FROM hugetable", function(rows) {
var result = rows;
});
console.log("Hello World");</pre>
<p>
Here, instead of expecting <em>database.query()</em> to directly
return a result to us, we pass it a second parameter, an anonymous
function.
</p>
<p>
In its previous form, our code was synchronous: <em>first</em>
do the database query, and only when this is done, <em>then</em>
write to the console.
</p>
<p>
Now, Node.js can handle the database request asynchronously.
Provided that <em>database.query()</em> is part of an asynchronous
library, this is what Node.js does: just as before, it takes the
query and sends it to the database. But instead of waiting for it
to be finished, it makes a mental note that says "When at some
point in the future the database server is done and sends the
result of the query, then I have to execute the anonymous function
that was passed to <em>database.query()</em>."
</p>
<p>
Then, it immediately executes <em>console.log()</em>, and
afterwards, it enters the event loop. Node.js continuously cycles
through this loop again and again whenever there is nothing else
to do, waiting for events. Events like, e.g., a slow database
query finally delivering its results.
</p>
<p>
This also explains why our HTTP server needs a function it can
call upon incoming requests - if Node.js would start the server
and then just pause, waiting for the next request, continuing
only when it arrives, that would be highly inefficent. If a second
user requests the server while it is still serving the first
request, that second request could only be answered after the first
one is done - as soon as you have more than a handful of HTTP
requests per second, this wouldn't work at all.
</p>
<p>
It's important to note that this asynchronous, single-threaded,
event-driven execution model isn't an infinitely scalable