Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 624 lines (433 sloc) 24.885 kB
2a420a7 @tj No longer gitignoring html
tj authored
1 <html>
2 <head>
3 <title>Mastering Node</title>
4 <style>
5 body {
69df60f @tj Added crappy default theme
tj authored
6 font: 14px/1.4 "Lucida Grande", "Helvetica Neue", Arial, sans-serif;
2a420a7 @tj No longer gitignoring html
tj authored
7 padding: 50px 180px;
8 }
69df60f @tj Added crappy default theme
tj authored
9 h1 {
10 padding-left: 5px;
11 border-bottom: 3px solid #eee;
12 }
13 pre {
14 margin: 15px 0;
15 padding: 15px;
16 border: 1px solid #eee;
17 }
18 a {
19 color: #00aaff;
20 }
09d5c0f @tj Fixed head markup
tj authored
21 </style>
22 </head>
23 <body><div class='mp'>
2a420a7 @tj No longer gitignoring html
tj authored
24 <h1>Mastering Node</h1>
25 <p><a href="http://nodejs.org/">Node</a> is an exciting new platform developed by <em>Ryan Dahl</em>, allowing JavaScript developers to create extremely high performance servers by leveraging <a href="http://code.google.com/p/v8/">Google's V8</a> JavaScript engine, and asynchronous I/O. In <em>Mastering Node</em> we will discover how to write high concurrency web servers, utilizing the CommonJS module system, node's core libraries, third party modules, high level web development and more.</p>
26
27 </div>
28 <div class='mp'>
29 <h1>Installing Node</h1>
fa384c9 @tj Regenerated book
tj authored
30 <p>In this chapter we will be looking at the installation and compilation of node. Although there are several ways we may install node, we will be looking at <a href="http://github.com/mxcl/homebrew">homebrew</a>, <a href="http://github.com/visionmedia/ndistro">nDistro</a>, and the most flexible method, of course - compiling from source.</p>
2a420a7 @tj No longer gitignoring html
tj authored
31
32 <h3 id="Homebrew">Homebrew</h3>
33
34 <p>Homebrew is a package management system for <em>OSX</em> written in Ruby, is extremely well adopted, and easy to use. To install node via the <code>brew</code> executable simply run:</p>
35
36 <pre><code>$ brew install node.js
37 </code></pre>
38
39 <h2 id="nDistro">nDistro</h2>
40
41 <p><a href="http://github.com/visionmedia/ndistro">nDistro</a> is a distribution toolkit for node, which allows creation and installation of node distros within seconds. An <em>nDistro</em> is simply a dotfile named <em>.ndistro</em> which defines
42 module and node binary version dependencies. In the example
43 below we specify the node binary version <em>0.1.102</em>, as well as
44 several 3rd party modules.</p>
45
46 <pre><code>node 0.1.102
47 module senchalabs connect
48 module visionmedia express 1.0.0beta2
49 module visionmedia connect-form
50 module visionmedia connect-redis
51 module visionmedia jade
52 module visionmedia ejs
53 </code></pre>
54
55 <p>Any machine that can run a shell script can install distributions, and keeps dependencies defined to a single directory structure, making it easy to maintain an deploy. nDistro uses <a href="http://github.com/visionmedia/nodes">pre-compiled node binaries</a> making them extremely fast to install, and module tarballs which are fetched from <a href="http://github.com">GitHub</a> via <em>wget</em> or <em>curl</em> (auto detected).</p>
56
57 <p>To get started we first need to install nDistro itself, below we <em>cd</em> to our bin directory of choice, <em>curl</em> the shell script, and pipe the response to <em>sh</em> which will install nDistro to the current directory:</p>
58
59 <pre><code>$ cd /usr/local/bin &amp;&amp; curl http://github.com/visionmedia/ndistro/raw/master/install | sh
60 </code></pre>
61
62 <p>Next we can place the contents of our example in <em>./.ndistro</em>, and execute <em>ndistro</em> with no arguments, prompting the program to load the config, and start installing:</p>
63
64 <pre><code>$ ndistro
65 </code></pre>
66
fa384c9 @tj Regenerated book
tj authored
67 <p>Installation of the example took less than 17 seconds on my machine, and outputs the following <em>stdout</em> indicating success. Not bad for an entire stack!</p>
2a420a7 @tj No longer gitignoring html
tj authored
68
69 <pre><code>... installing node-0.1.102-i386
70 ... installing connect
71 ... installing express 1.0.0beta2
72 ... installing bin/express
73 ... installing connect-form
74 ... installing connect-redis
75 ... installing jade
76 ... installing bin/jade
77 ... installing ejs
78 ... installation complete
79 </code></pre>
80
81 <h2 id="Building-From-Source">Building From Source</h2>
82
83 <p>To build and install node from source, we first need to obtain the code. The first method of doing so is
84 via <code>git</code>, if you have git installed you can execute:</p>
85
86 <pre><code>$ git clone http://github.com/ry/node.git &amp;&amp; cd node
87 </code></pre>
88
89 <p>For those without <em>git</em>, or who prefer not to use it, we can also download the source via <em>curl</em>, <em>wget</em>, or similar:</p>
90
91 <pre><code>$ curl -# http://nodejs.org/dist/node-v0.1.99.tar.gz &gt; node.tar.gz
92 $ tar -zxf node.tar.gz
93 </code></pre>
94
95 <p>Now that we have the source on our machine, we can run <code>./configure</code> which discovers which libraries are available for node to utilize such as <em>OpenSSL</em> for transport security support, C and C++ compilers, etc. <code>make</code> which builds node, and finally <code>make install</code> which will install node.</p>
96
97 <pre><code>$ ./configure &amp;&amp; make &amp;&amp; make install
98 </code></pre>
99
100 </div>
101 <div class='mp'>
102 <h1>Globals</h1>
ef20620 Clean up flow of Globals chapter intro paragraph
Grant Heaslip authored
103 <p> As we have learnt, node's module system discourages the use of globals; however node provides a few important globals for use to utilize. The first and most important is the <code>process</code> global, which exposes process manipulation such as signalling, exiting, the process id (pid), and more. Other globals, such as the <code>console</code> object, are provided to those used to writing JavaScript for web browsers.</p>
2a420a7 @tj No longer gitignoring html
tj authored
104
105 <h2 id="console">console</h2>
106
fdf60a0 Clean up some console object descriptions
Grant Heaslip authored
107 <p>The <code>console</code> object contains several methods which are used to output information to <em>stdout</em> or <em>stderr</em>. Let's take a look at what each method does:</p>
2a420a7 @tj No longer gitignoring html
tj authored
108
109 <h3 id="console-log-">console.log()</h3>
110
fdf60a0 Clean up some console object descriptions
Grant Heaslip authored
111 <p>The most frequently used console method is <code>console.log()</code>, which simply writes to <em>stdout</em> and appends a line feed (<code>\n</code>). Currently aliased as <code>console.info()</code>.</p>
2a420a7 @tj No longer gitignoring html
tj authored
112
113 <pre><code>console.log('wahoo');
114 // =&gt; wahoo
115
116 console.log({ foo: 'bar' });
117 // =&gt; [object Object]
118 </code></pre>
119
120 <h3 id="console-error-">console.error()</h3>
121
122 <p>Identical to <code>console.log()</code>, however writes to <em>stderr</em>. Aliased as <code>console.warn()</code> as well.</p>
123
124 <pre><code>console.error('database connection failed');
125 </code></pre>
126
127 <h3 id="console-dir-">console.dir()</h3>
128
129 <p>Utilizes the <em>sys</em> module's <code>inspect()</code> method to pretty-print the object to
130 <em>stdout</em>.</p>
131
132 <pre><code>console.dir({ foo: 'bar' });
133 // =&gt; { foo: 'bar' }
134 </code></pre>
135
136 <h3 id="console-assert-">console.assert()</h3>
137
138 <p>Asserts that the given expression is truthy, or throws an exception.</p>
139
140 <pre><code>console.assert(connected, 'Database connection failed');
141 </code></pre>
142
143 <h2 id="process">process</h2>
144
65f2cdd Clean up process object descriptions
Grant Heaslip authored
145 <p>The <code>process</code> object is plastered with goodies. First we will take a look
146 at some properties that provide information about the node process itself:</p>
2a420a7 @tj No longer gitignoring html
tj authored
147
148 <h3 id="process-version">process.version</h3>
149
65f2cdd Clean up process object descriptions
Grant Heaslip authored
150 <p>The node version string, for example "v0.1.103".</p>
2a420a7 @tj No longer gitignoring html
tj authored
151
152 <h3 id="process-installPrefix">process.installPrefix</h3>
153
65f2cdd Clean up process object descriptions
Grant Heaslip authored
154 <p>The installation prefix. In my case "<em>/usr/local</em>", as node's binary was installed to "<em>/usr/local/bin/node</em>".</p>
2a420a7 @tj No longer gitignoring html
tj authored
155
156 <h3 id="process-execPath">process.execPath</h3>
157
65f2cdd Clean up process object descriptions
Grant Heaslip authored
158 <p>The path to the executable itself "<em>/usr/local/bin/node</em>".</p>
2a420a7 @tj No longer gitignoring html
tj authored
159
160 <h3 id="process-platform">process.platform</h3>
161
65f2cdd Clean up process object descriptions
Grant Heaslip authored
162 <p>The platform you are running on. For example, "darwin".</p>
2a420a7 @tj No longer gitignoring html
tj authored
163
164 <h3 id="process-pid">process.pid</h3>
165
166 <p>The process id.</p>
167
168 <h3 id="process-cwd-">process.cwd()</h3>
169
65f2cdd Clean up process object descriptions
Grant Heaslip authored
170 <p>Returns the current working directory. For example:</p>
2a420a7 @tj No longer gitignoring html
tj authored
171
172 <pre><code>cd ~ &amp;&amp; node
173 node&gt; process.cwd()
174 "/Users/tj"
175 </code></pre>
176
177 <h3 id="process-chdir-">process.chdir()</h3>
178
179 <p>Changes the current working directory to the path passed.</p>
180
181 <pre><code>process.chdir('/foo');
182 </code></pre>
183
184 <h3 id="process-getuid-">process.getuid()</h3>
185
186 <p>Returns the numerical user id of the running process.</p>
187
188 <h3 id="process-setuid-">process.setuid()</h3>
189
190 <p>Sets the effective user id for the running process. This method accepts both a numerical id, as well as a string. For example both <code>process.setuid(501)</code>, and <code>process.setuid('tj')</code> are valid.</p>
191
192 <h3 id="process-getgid-">process.getgid()</h3>
193
194 <p>Returns the numerical group id of the running process.</p>
195
196 <h3 id="process-setgid-">process.setgid()</h3>
197
65f2cdd Clean up process object descriptions
Grant Heaslip authored
198 <p>Similar to <code>process.setuid()</code> however operates on the group, also accepting a numerical value or string representation. For example, <code>process.setgid(20)</code> or <code>process.setgid('www')</code>.</p>
2a420a7 @tj No longer gitignoring html
tj authored
199
200 <h3 id="process-env">process.env</h3>
201
65f2cdd Clean up process object descriptions
Grant Heaslip authored
202 <p>An object containing the user's environment variables. For example:</p>
2a420a7 @tj No longer gitignoring html
tj authored
203
204 <pre><code>{ PATH: '/Users/tj/.gem/ruby/1.8/bin:/Users/tj/.nvm/current/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin'
205 , PWD: '/Users/tj/ebooks/masteringnode'
206 , EDITOR: 'mate'
207 , LANG: 'en_CA.UTF-8'
208 , SHLVL: '1'
209 , HOME: '/Users/tj'
210 , LOGNAME: 'tj'
211 , DISPLAY: '/tmp/launch-YCkT03/org.x:0'
212 , _: '/usr/local/bin/node'
213 , OLDPWD: '/Users/tj'
214 }
215 </code></pre>
216
217 <h3 id="process-argv">process.argv</h3>
218
219 <p>When executing a file with the <code>node</code> executable <code>process.argv</code> provides access to the argument vector, the first value being the node executable, second being the filename, and remaining values being the arguments passed.</p>
220
65f2cdd Clean up process object descriptions
Grant Heaslip authored
221 <p>For example, our source file <em>./src/process/misc.js</em> can be executed by running:</p>
2a420a7 @tj No longer gitignoring html
tj authored
222
223 <pre><code>$ node src/process/misc.js foo bar baz
224 </code></pre>
225
226 <p>in which we call <code>console.dir(process.argv)</code>, outputting the following:</p>
227
228 <pre><code>[ 'node'
229 , '/Users/tj/EBooks/masteringnode/src/process/misc.js'
230 , 'foo'
231 , 'bar'
232 , 'baz'
233 ]
234 </code></pre>
235
236 <h3 id="process-exit-">process.exit()</h3>
237
65f2cdd Clean up process object descriptions
Grant Heaslip authored
238 <p>The <code>process.exit()</code> method is synonymous with the C function <code>exit()</code>, in which an exit code > 0 is passed to indicate failure, or 0 is passed to indicate success. When invoked, the <em>exit</em> event is emitted, allowing a short time for arbitrary processing to occur before <code>process.reallyExit()</code> is called with the given status code.</p>
2a420a7 @tj No longer gitignoring html
tj authored
239
240 <h3 id="process-on-">process.on()</h3>
241
65f2cdd Clean up process object descriptions
Grant Heaslip authored
242 <p>The process itself is an <code>EventEmitter</code>, allowing you to do things like listen for uncaught exceptions via the <em>uncaughtException</em> event:</p>
2a420a7 @tj No longer gitignoring html
tj authored
243
244 <pre><code>process.on('uncaughtException', function(err){
245 console.log('got an error: %s', err.message);
246 process.exit(1);
247 });
248
249 setTimeout(function(){
250 throw new Error('fail');
251 }, 100);
252 </code></pre>
253
254 <h3 id="process-kill-">process.kill()</h3>
255
65f2cdd Clean up process object descriptions
Grant Heaslip authored
256 <p><code>process.kill()</code> method sends the signal passed to the given <em>pid</em>, defaulting to <strong>SIGINT</strong>. In the example below, we send the <strong>SIGTERM</strong> signal to the same node process to illustrate signal trapping, after which we output "terminating" and exit. Note that the second timeout of 1000 milliseconds is never reached.</p>
2a420a7 @tj No longer gitignoring html
tj authored
257
258 <pre><code>process.on('SIGTERM', function(){
259 console.log('terminating');
260 process.exit(1);
261 });
262
263 setTimeout(function(){
264 console.log('sending SIGTERM to process %d', process.pid);
265 process.kill(process.pid, 'SIGTERM');
266 }, 500);
267
268 setTimeout(function(){
269 console.log('never called');
270 }, 1000);
271 </code></pre>
272
273 <h3 id="errno">errno</h3>
274
65f2cdd Clean up process object descriptions
Grant Heaslip authored
275 <p>The <code>process</code> object is host of the error numbers, which reference what you would find in C-land. For example, <code>process.EPERM</code> represents a permission based error, while <code>process.ENOENT</code> represents a missing file or directory. Typically these are used within bindings to bridge the gap between C++ and JavaScript, but they're useful for handling exceptions as well:</p>
2a420a7 @tj No longer gitignoring html
tj authored
276
277 <pre><code>if (err.errno === process.ENOENT) {
278 // Display a 404 "Not Found" page
279 } else {
280 // Display a 500 "Internal Server Error" page
281 }
282 </code></pre>
283
284 </div>
285 <div class='mp'>
286 <h1>Events</h1>
9b1e95a Clean up events chapter
Grant Heaslip authored
287 <p> The concept of an "event" is crucial to node, and is used heavily throughout core and 3rd-party modules. Node's core module <em>events</em> supplies us with a single constructor, <em>EventEmitter</em>.</p>
2a420a7 @tj No longer gitignoring html
tj authored
288
289 <h2 id="Emitting-Events">Emitting Events</h2>
290
9b1e95a Clean up events chapter
Grant Heaslip authored
291 <p>Typically an object inherits from <em>EventEmitter</em>, however our small example below illustrates the API. First we create an <code>emitter</code>, after which we can define any number of callbacks using the <code>emitter.on()</code> method, which accepts the <em>name</em> of the event and arbitrary objects passed as data. When <code>emitter.emit()</code> is called, we are only required to pass the event <em>name</em>, followed by any number of arguments (in this case the <code>first</code> and <code>last</code> name strings).</p>
2a420a7 @tj No longer gitignoring html
tj authored
292
293 <pre><code>var EventEmitter = require('events').EventEmitter;
294
295 var emitter = new EventEmitter;
296
297 emitter.on('name', function(first, last){
298 console.log(first + ', ' + last);
299 });
300
301 emitter.emit('name', 'tj', 'holowaychuk');
302 emitter.emit('name', 'simon', 'holowaychuk');
303 </code></pre>
304
305 <h2 id="Inheriting-From-EventEmitter">Inheriting From EventEmitter</h2>
306
9b1e95a Clean up events chapter
Grant Heaslip authored
307 <p>A more practical and common use of <code>EventEmitter</code> is to inherit from it. This means we can leave <code>EventEmitter</code>'s prototype untouched while utilizing its API for our own means of world domination!</p>
2a420a7 @tj No longer gitignoring html
tj authored
308
9b1e95a Clean up events chapter
Grant Heaslip authored
309 <p>To do so, we begin by defining the <code>Dog</code> constructor, which of course will bark from time to time (also known as an <em>event</em>).</p>
2a420a7 @tj No longer gitignoring html
tj authored
310
311 <pre><code>var EventEmitter = require('events').EventEmitter;
312
313 function Dog(name) {
314 this.name = name;
315 }
316 </code></pre>
317
9b1e95a Clean up events chapter
Grant Heaslip authored
318 <p>Here we inherit from <code>EventEmitter</code> so we can use the methods it provides, such as <code>EventEmitter#on()</code> and <code>EventEmitter#emit()</code>. If the <code>__proto__</code> property is throwing you off, don't worry, we'll be coming back to this later.</p>
2a420a7 @tj No longer gitignoring html
tj authored
319
320 <pre><code>Dog.prototype.__proto__ = EventEmitter.prototype;
321 </code></pre>
322
9b1e95a Clean up events chapter
Grant Heaslip authored
323 <p>Now that we have our <code>Dog</code> set up, we can create... Simon! When Simon barks, we can let <em>stdout</em> know by calling <code>console.log()</code> within the callback. The callback itself is called in the context of the object (aka <code>this</code>).</p>
2a420a7 @tj No longer gitignoring html
tj authored
324
325 <pre><code>var simon = new Dog('simon');
326
327 simon.on('bark', function(){
328 console.log(this.name + ' barked');
329 });
330 </code></pre>
331
9b1e95a Clean up events chapter
Grant Heaslip authored
332 <p>Bark twice per second:</p>
2a420a7 @tj No longer gitignoring html
tj authored
333
334 <pre><code>setInterval(function(){
335 simon.emit('bark');
336 }, 500);
337 </code></pre>
338
339 <h2 id="Removing-Event-Listeners">Removing Event Listeners</h2>
340
9b1e95a Clean up events chapter
Grant Heaslip authored
341 <p>As we have seen, event listeners are simply functions which are called when we <code>emit()</code> an event. We can remove these listeners by calling the <code>removeListener(type, callback)</code> method, although this isn't seen often. In the example below we emit the <em>message</em> "foo bar" every <code>300</code> milliseconds, which has a callback of <code>console.log()</code>. After 1000 milliseconds, we call <code>removeListener()</code> with the same arguments that we passed to <code>on()</code> originally. We could also have used <code>removeAllListeners(type)</code>, which removes all listeners registered to the given <em>type</em>.</p>
2a420a7 @tj No longer gitignoring html
tj authored
342
343 <pre><code>var EventEmitter = require('events').EventEmitter;
344
345 var emitter = new EventEmitter;
346
347 emitter.on('message', console.log);
348
349 setInterval(function(){
350 emitter.emit('message', 'foo bar');
351 }, 300);
352
353 setTimeout(function(){
354 emitter.removeListener('message', console.log);
355 }, 1000);
356 </code></pre>
357
358 </div>
359 <div class='mp'>
360 <h1>Buffers</h1>
7faeaaa Clean up buffers chapter
Grant Heaslip authored
361 <p> To handle binary data, node provides us with the global <code>Buffer</code> object. <code>Buffer</code> instances represent memory allocated independently of V8's heap. There are several ways to construct a <code>Buffer</code> instance, and many ways you can manipulate its data.</p>
2a420a7 @tj No longer gitignoring html
tj authored
362
7faeaaa Clean up buffers chapter
Grant Heaslip authored
363 <p>The simplest way to construct a <code>Buffer</code> from a string is to simply pass a string as the first argument. As you can see in the log output, we now have a buffer object containing 5 bytes of data represented in hexadecimal.</p>
2a420a7 @tj No longer gitignoring html
tj authored
364
365 <pre><code>var hello = new Buffer('Hello');
366
367 console.log(hello);
368 // =&gt; &lt;Buffer 48 65 6c 6c 6f>
369
370 console.log(hello.toString());
371 // =&gt; "Hello"
372 </code></pre>
373
7faeaaa Clean up buffers chapter
Grant Heaslip authored
374 <p>By default, the encoding is "utf8", but this can be overridden by passing a string as the second argument. For example, the ellipsis below will be printed to stdout as the "&amp;" character when in "ascii" encoding.</p>
2a420a7 @tj No longer gitignoring html
tj authored
375
376 <pre><code>var buf = new Buffer('…');
377 console.log(buf.toString());
378 // =&gt;
379
380 var buf = new Buffer('…', 'ascii');
381 console.log(buf.toString());
382 // =&gt; &amp;
383 </code></pre>
384
7faeaaa Clean up buffers chapter
Grant Heaslip authored
385 <p>An alternative (but in this case functionality equivalent) method is to pass an array of integers representing the octet stream.</p>
2a420a7 @tj No longer gitignoring html
tj authored
386
387 <pre><code>var hello = new Buffer([0x48, 0x65, 0x6c, 0x6c, 0x6f]);
388 </code></pre>
389
7faeaaa Clean up buffers chapter
Grant Heaslip authored
390 <p>Buffers can also be created with an integer representing the number of bytes allocated, after which we can call the <code>write()</code> method, providing an optional offset and encoding. Below, we provide an offset of 2 bytes to our second call to <code>write()</code> (buffering "Hel") and then write another two bytes with an offset of 3 (completing "Hello").</p>
2a420a7 @tj No longer gitignoring html
tj authored
391
392 <pre><code>var buf = new Buffer(5);
393 buf.write('He');
394 buf.write('l', 2);
395 buf.write('lo', 3);
396 console.log(buf.toString());
397 // =&gt; "Hello"
398 </code></pre>
399
7faeaaa Clean up buffers chapter
Grant Heaslip authored
400 <p>The <code>.length</code> property of a buffer instance contains the byte length of the stream, as opposed to native strings, which simply return the number of characters. For example, the ellipsis character '…' consists of three bytes, so the buffer will respond with the byte length (3), and not the character length (1).</p>
2a420a7 @tj No longer gitignoring html
tj authored
401
402 <pre><code>var ellipsis = new Buffer('…', 'utf8');
403
404 console.log('… string length: %d', '…'.length);
405 // =&gt; … string length: 1
406
407 console.log('… byte length: %d', ellipsis.length);
408 // =&gt; … byte length: 3
409
410 console.log(ellipsis);
411 // =&gt; &lt;Buffer e2 80 a6>
412 </code></pre>
413
7faeaaa Clean up buffers chapter
Grant Heaslip authored
414 <p>To determine the byte length of a native string, pass it to the <code>Buffer.byteLength()</code> method.</p>
2a420a7 @tj No longer gitignoring html
tj authored
415
7faeaaa Clean up buffers chapter
Grant Heaslip authored
416 <p>The API is written in such a way that it is String-like. For example, we can work with "slices" of a <code>Buffer</code> by passing offsets to the <code>slice()</code> method:</p>
2a420a7 @tj No longer gitignoring html
tj authored
417
418 <pre><code>var chunk = buf.slice(4, 9);
419 console.log(chunk.toString());
420 // =&gt; "some"
421 </code></pre>
422
7faeaaa Clean up buffers chapter
Grant Heaslip authored
423 <p>Alternatively, when expecting a string, we can pass offsets to <code>Buffer#toString()</code>:</p>
2a420a7 @tj No longer gitignoring html
tj authored
424
425 <pre><code>var buf = new Buffer('just some data');
426 console.log(buf.toString('ascii', 4, 9));
427 // =&gt; "some"
428 </code></pre>
429
430 </div>
431 <div class='mp'>
432 <h1>Streams</h1>
97cb9fe Clean up streams chapter
Grant Heaslip authored
433 <p> Streams are an important concept in node. The stream API is a unified way to handle stream-like data. For example, data can be streamed to a file, streamed to a socket to respond to an HTTP request, or streamed from a read-only source such as <em>stdin</em>. For now, we'll concentrate on the API, leaving stream specifics to later chapters.</p>
2a420a7 @tj No longer gitignoring html
tj authored
434
435 <h2 id="Readable-Streams">Readable Streams</h2>
436
437 <p> Readable streams such as an HTTP request inherit from <code>EventEmitter</code> in order to expose incoming data through events. The first of these events is the <em>data</em> event, which is an arbitrary chunk of data passed to the event handler as a <code>Buffer</code> instance.</p>
438
439 <pre><code>req.on('data', function(buf){
440 // Do something with the Buffer
441 });
442 </code></pre>
443
97cb9fe Clean up streams chapter
Grant Heaslip authored
444 <p>As we know, we can call <code>toString()</code> on a buffer to return a string representation of the binary data. Likewise, we can call <code>setEncoding()</code> on a stream, after which the <em>data</em> event will emit strings.</p>
2a420a7 @tj No longer gitignoring html
tj authored
445
446 <pre><code>req.setEncoding('utf8');
447 req.on('data', function(str){
448 // Do something with the String
449 });
450 </code></pre>
451
97cb9fe Clean up streams chapter
Grant Heaslip authored
452 <p>Another important event is <em>end</em>, which represents the ending of <em>data</em> events. For example, here's an HTTP echo server, which simply "pumps" the request body data through to the response. So if we POST "hello world", our response will be "hello world".</p>
2a420a7 @tj No longer gitignoring html
tj authored
453
454 <pre><code>var http = require('http');
455
456 http.createServer(function(req, res){
457 res.writeHead(200);
458 req.on('data', function(data){
459 res.write(data);
460 });
461 req.on('end', function(){
462 res.end();
463 });
464 }).listen(3000);
465 </code></pre>
466
97cb9fe Clean up streams chapter
Grant Heaslip authored
467 <p>The <em>sys</em> module actually has a function designed specifically for this "pumping" action, aptly named <code>sys.pump()</code>. It accepts a read stream as the first argument, and write stream as the second.</p>
2a420a7 @tj No longer gitignoring html
tj authored
468
469 <pre><code>var http = require('http'),
470 sys = require('sys');
471
472 http.createServer(function(req, res){
473 res.writeHead(200);
474 sys.pump(req, res);
475 }).listen(3000);
476 </code></pre>
477
478 </div>
479 <div class='mp'>
480 <h1>File System</h1>
15dc0e8 Clean up file system chapter
Grant Heaslip authored
481 <p> To work with the filesystem, node provides the "fs" module. The commands emulate the POSIX operations, and most methods work synchronously or asynchronously. We will look at how to use both, then establish which is the better option.</p>
960af03 @tj Regenerated book
tj authored
482
483 <h2 id="Working-with-the-filesystem">Working with the filesystem</h2>
484
15dc0e8 Clean up file system chapter
Grant Heaslip authored
485 <p> Lets start with a basic example of working with the filesystem. This example creates a directory, creates a file inside it, then writes the contents of the file to console:</p>
960af03 @tj Regenerated book
tj authored
486
487 <pre><code>var fs = require('fs');
488
489 fs.mkdir('./helloDir',0777, function (err) {
490 if (err) throw err;
491
492 fs.writeFile('./helloDir/message.txt', 'Hello Node', function (err) {
493 if (err) throw err;
494 console.log('file created with contents:');
495
496 fs.readFile('./helloDir/message.txt','UTF-8' ,function (err, data) {
497 if (err) throw err;
498 console.log(data);
499 });
500 });
501 });
502 </code></pre>
503
15dc0e8 Clean up file system chapter
Grant Heaslip authored
504 <p> As evident in the example above, each callback is placed in the previous callback &mdash; these are referred to as chainable callbacks. This pattern should be followed when using asynchronous methods, as there's no guarantee that the operations will be completed in the order they're created. This could lead to unpredictable behavior.</p>
960af03 @tj Regenerated book
tj authored
505
506 <p> The example can be rewritten to use a synchronous approach:</p>
507
508 <pre><code>fs.mkdirSync('./helloDirSync',0777);
509 fs.writeFileSync('./helloDirSync/message.txt', 'Hello Node');
510 var data = fs.readFileSync('./helloDirSync/message.txt','UTF-8');
511 console.log('file created with contents:');
512 console.log(data);
513 </code></pre>
514
15dc0e8 Clean up file system chapter
Grant Heaslip authored
515 <p> It is better to use the asynchronous approach on servers with a high load, as the synchronous methods will cause the whole process to halt and wait for the operation to complete. This will block any incoming connections or other events.</p>
960af03 @tj Regenerated book
tj authored
516
517 <h2 id="File-information">File information</h2>
518
15dc0e8 Clean up file system chapter
Grant Heaslip authored
519 <p> The fs.Stats object contains information about a particular file or directory. This can be used to determine what type of object we're working with. In this example, we're getting all the file objects in a directory and displaying whether they're a file or a
960af03 @tj Regenerated book
tj authored
520 directory object.</p>
521
522 <pre><code>var fs = require('fs');
523
524 fs.readdir('/etc/', function (err, files) {
525 if (err) throw err;
526
527 files.forEach( function (file) {
528 fs.stat('/etc/' + file, function (err, stats) {
529 if (err) throw err;
530
531 if (stats.isFile()) {
532 console.log("%s is file", file);
533 }
534 else if (stats.isDirectory ()) {
535 console.log("%s is a directory", file);
536 }
537 console.log('stats: %s',JSON.stringify(stats));
538 });
539 });
540 });
541 </code></pre>
542
543 <h2 id="Watching-files">Watching files</h2>
544
15dc0e8 Clean up file system chapter
Grant Heaslip authored
545 <p> The fs.watchfile method monitors a file and fires an event whenever the file is changed.</p>
960af03 @tj Regenerated book
tj authored
546
547 <pre><code>var fs = require('fs');
548
549 fs.watchFile('./testFile.txt', function (curr, prev) {
550 console.log('the current mtime is: ' + curr.mtime);
551 console.log('the previous mtime was: ' + prev.mtime);
552 });
553
554 fs.writeFile('./testFile.txt', "changed", function (err) {
555 if (err) throw err;
556
557 console.log("file write complete");
558 });
559 </code></pre>
560
15dc0e8 Clean up file system chapter
Grant Heaslip authored
561 <p> A file can also be unwatched using the fs.unwatchFile method call. This should be used once a file no longer needs to be monitored.</p>
960af03 @tj Regenerated book
tj authored
562
563 <h2 id="Nodejs-Docs-for-further-reading">Nodejs Docs for further reading</h2>
564
15dc0e8 Clean up file system chapter
Grant Heaslip authored
565 <p> The node API <a href="http://nodejs.org/api.html#file-system-106">docs</a> are very detailed and list all the possible filesystem commands
960af03 @tj Regenerated book
tj authored
566 available when working with Nodejs.</p>
2a420a7 @tj No longer gitignoring html
tj authored
567
568 </div>
569 <div class='mp'>
570 <h1>TCP</h1>
571 <p> ...</p>
572
573 <h2 id="TCP-Servers">TCP Servers</h2>
574
575 <p> ...</p>
576
577 <h2 id="TCP-Clients">TCP Clients</h2>
578
579 <p> ...</p>
580
581 </div>
582 <div class='mp'>
583 <h1>HTTP</h1>
584 <p> ...</p>
585
586 <h2 id="HTTP-Servers">HTTP Servers</h2>
587
588 <p> ...</p>
589
590 <h2 id="HTTP-Clients">HTTP Clients</h2>
591
592 <p> ...</p>
593
594 </div>
595 <div class='mp'>
596 <h1>Connect</h1>
597 <p>Connect is a ...</p>
598
599 </div>
600 <div class='mp'>
601 <h1>Express</h1>
602 <p>Express is a ...</p>
603
604 </div>
605 <div class='mp'>
606 <h1>Testing</h1>
607 <p> ...</p>
608
609 <h2 id="Expresso">Expresso</h2>
610
611 <p> ...</p>
612
613 <h2 id="Vows">Vows</h2>
614
615 <p> ...</p>
616
617 </div>
618 <div class='mp'>
619 <h1>Deployment</h1>
620 <p> ...</p>
621
622 </div>
623 </body>
624 </html>
Something went wrong with that request. Please try again.