You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 03-Coordinating-IO/content.md
+60-49
Original file line number
Diff line number
Diff line change
@@ -1,15 +1,16 @@
1
-
# 2 Coordinating I/O
1
+
# 3 Coordinating I/O
2
2
3
3
This chapter covers the following topics
4
4
5
-
* File reading, writing, appending
6
-
* File system metadata
7
-
* STDOUT, STDIN, STDERR
8
-
* Communicating with sockets
5
+
* Interfacing with standard I/O
6
+
* Working with files
7
+
* Fetching meta-data
8
+
* Watching files and directories
9
+
* Communicating over sockets
9
10
10
11
## Introduction
11
12
12
-
Operationally, Node.js is C with JavaScript's clothes on.
13
+
Operationally, Node.js is C/C++ with JavaScript's clothes on.
13
14
Just like C and other low-level environments, Node interacts with the Operating System at a fundamental level: Input and Output.
14
15
15
16
In this chapter we'll explore some core API's provided by Node, along with
@@ -18,12 +19,11 @@ the file system, and the network stack.
18
19
19
20
## Interfacing with standard I/O
20
21
21
-
Standard I/O relates to the predefined input, output and error data channels that connect a process to a shell terminal. Of course these can be redirected and piped
22
-
to other programs for further processing, storage and so on.
22
+
Standard I/O relates to the predefined input, output and error data channels that connect a process to a shell terminal, commonly known as STDIN, STDOUT and STDERR. Of course these can be redirected and piped to other programs for further processing, storage and so on.
23
23
24
-
Node provides access standard I/O on the global `process` object.
24
+
Node provides access to standard I/O on the global `process` object.
25
25
26
-
In this recipe we're going to take some input, use it form output, and simultaneously log to the standard error channel.
26
+
In this recipe we're going to take some input, use it to form some data which we'll send to STDOUT, while simultaneously logging to STDERR.
27
27
28
28
### Getting Ready
29
29
@@ -97,7 +97,7 @@ aGkKdGhlcmUK
97
97
98
98
The standard I/O channels are implemented using Node.js Streams.
99
99
100
-
We'll find out more about these in **Chapter 3 Using Streams**, we also have an example in the **There's more** section of this recipe of using the standard
100
+
We'll find out more about these in **Chapter 4 Using Streams**, we also have an example in the **There's more** section of this recipe of using the standard
101
101
I/O channels as streams.
102
102
103
103
Suffice it to say, that Node `Stream` instances (instantiated from Node's core `stream` module) inherit from `EventEmitter` (from Node's core `events` module), and emit a `data` event for every chunk of data received.
@@ -119,7 +119,7 @@ Let's take a look at how Node Streams wrap Standard I/O channels, and how to det
119
119
120
120
#### Piping
121
121
122
-
As mentioned in the main recipe, the standard I/O channels available on the global `process` object are implementations of a core Node abstraction: streams. We'll be covering these in much greater detail in **Chapter 3 Using Streams** but for now let's see how we could achieve an equivalent effect using Node Streams' `pipe` method.
122
+
As mentioned in the main recipe, the standard I/O channels available on the global `process` object are implementations of a core Node abstraction: streams. We'll be covering these in much greater detail in **Chapter 4 Using Streams** but for now let's see how we could achieve an equivalent effect using Node Streams' `pipe` method.
123
123
124
124
For this example we need the third party `base64-encode-stream` module, so let's open a terminal and run the following commands:
125
125
@@ -170,8 +170,8 @@ true
170
170
> result. There's also the related `-e` flag which only evaluates a
171
171
> supplied command line string, but doesn't output it's return value.
172
172
173
-
We're running `node` directly, so the Standard In channel is correctly
174
-
identified as a TTY.
173
+
We're running `node` directly, so our STDIN is correctly identified as
174
+
a TTY input.
175
175
176
176
Now let's try the following:
177
177
@@ -190,9 +190,10 @@ Knowing whether a process is directly connected to a terminal can be useful in c
190
190
191
191
### See also
192
192
193
-
* TODO
194
-
* ...chapter 3
195
-
* .. anywhere else the process object is discussed
193
+
**Creating a Node.js WebSocket client* in the *There's More* section of *Communicating with WebSockets* in **Chapter 5 Wielding Web Protocols**
194
+
**Using the pipe method* in **Chapter 4 Using Streams**
195
+
**Getting symlink information* in the *There's More* section of *Fetching meta-data* in this chapter
196
+
196
197
197
198
## Working with files
198
199
@@ -201,8 +202,8 @@ to server side programming.
201
202
202
203
Node's `fs` module provides this ability.
203
204
204
-
In this recipe we'll learn how to read, write and append to files,
205
-
synchronously then we'll follow up in the **There's More** section showing how to perform the same operations asynchronously and incrementally.
205
+
In this recipe we'll learn how to read, write and append to files in a
206
+
synchronous manner. In the **There's More** section we'll explore how to perform the same operations asynchronously and incrementally.
206
207
207
208
### Getting Ready
208
209
@@ -211,7 +212,7 @@ We'll need a file to read.
211
212
We can use the following to populate a file with 1MB of data:
@@ -397,14 +402,18 @@ chunk and stripped result is discarded, whilst the next chunk enters
397
402
process memory. This all happens over multiple ticks of the event loop,
398
403
allowing room for processing of the interval timer queue.
399
404
400
-
We'll be delving much deeper into Streams in **Chapter 3 Using Streams**,
405
+
We'll be delving much deeper into Streams in **Chapter 4 Using Streams**,
401
406
but for the time being we can see that `fs.createReadStream` and `fs.createWriteStream` are, more often that not, the most suitable way to read
402
407
and write to files.
403
408
404
409
### See also
405
410
406
-
* TODO
407
-
* chapter 3...etc
411
+
**Receiving POST Data* in **Chapter 5 Wielding Web protocols**
412
+
**Deploying a full system* in **Chapter 11 Deploying Node.js**
413
+
**Multipart POST uploads* in **Chapter 5 Wielding Web protocols**
414
+
**Processing big data* in **Chapter 4 Using Streams**
415
+
**Creating an SMTP server* in **Chapter 5 Wielding Web protocols**
416
+
**Fetching meta-data* in this chapter
408
417
409
418
## Fetching meta-data
410
419
@@ -499,7 +508,7 @@ file in order to obtain information about it, then return that data, like so:
499
508
```js
500
509
functiontoMeta({file, dir}) {
501
510
conststats=fs.statSync(path.join(dir, file))
502
-
let {birthtime, ino, mode, nlink, size} = stats
511
+
var {birthtime, ino, mode, nlink, size} = stats
503
512
birthtime =birthtime.toUTCString()
504
513
mode =mode.toString(8)
505
514
size +='B'
@@ -657,7 +666,7 @@ in bold, if it isn't we write a in a dulled down white color.
657
666
Let's find out how to examine symlinks, check whether files exists and see how to
658
667
actually alter file system metadata.
659
668
660
-
#### Getting symlink information
669
+
#### Getting symlink information
661
670
662
671
There are other types of stat calls, one such call is `lstat` (the 'l' stands for link).
663
672
@@ -672,7 +681,7 @@ First we'll modify the `toMeta` function to use `fs.lstatSync` instead of
672
681
```js
673
682
functiontoMeta({file, dir}) {
674
683
conststats=fs.lstatSync(path.join(dir, file))
675
-
let {birthtime, ino, mode, nlink, size} = stats
684
+
var {birthtime, ino, mode, nlink, size} = stats
676
685
birthtime =birthtime.toUTCString()
677
686
mode =mode.toString(8)
678
687
size +='B'
@@ -793,9 +802,10 @@ exists(process.argv[2])
793
802
794
803
> #### Promises 
795
804
> For extra fun here (because the paradigm fits well in this case),
796
-
> we used the ES2015 native `Promise` abstraction. Find out more about
797
-
> promises at https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise
798
-
805
+
> we used the ES2015 native `Promise` abstraction. Find out more about promises at https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise
806
+
> In general we tend to use a minimal subset of ES2015 (ES6) throughout so we can focus more
807
+
> on using Node and less on syntax, avoiding either extra discourse or potential confusion.
808
+
> We should also note Promises are currently a poor choice for implementing production server logic in Node, due to (standards specified) opaque behaviors (error swallowing, asynchronous stack unwinding) leading to difficulties in production root cause analysis.
799
809
800
810
Now if we run the following:
801
811
@@ -827,7 +837,7 @@ If there's a problem accessing, an error will be logged, if not `null` will be l
827
837
828
838
829
839
> #### Modes and Bitmasks 
830
-
> For more on `fs.access` see the docs at https://nodejs.org/api/fs.html#fs_fs_access_path_mode_callback, to learn about bitmasks check out https://abdulapopoola.com/2016/05/30/understanding-bit-masks/
840
+
> For more on `fs.access` see the docs at https://nodejs.org/api/fs.html#fs_fs_access_path_mode_callback, to learn about bitmasks check out https://abdulapopoola.com/2016/05/30/understanding-bit-masks/
831
841
832
842
833
843
#### Manipulating metadata
@@ -838,7 +848,7 @@ Let's create a small program that creates a file, sets the UID and GID to `nobod
838
848
839
849
```js
840
850
constfs=require('fs')
841
-
const {execSync} =require('child_process')
851
+
const {execSync} =require('child_process')
842
852
843
853
constfile=process.argv[2]
844
854
if (!file) {
@@ -866,7 +876,7 @@ We used `fs.accessSync` to synchronously check for file existence, using a
866
876
`try/catch` since `fs.accessSync` throws when a file does not exist.
867
877
868
878
> #### try/catch 
869
-
> In this particular context, a try/catch is fine. However as a general rule we should avoid try/catch as much as possible. See [How to know when (not) to throw](http://www.nearform.com/nodecrunch/10-tips-coding-node-js-3-know-throw-2/) for more details.
879
+
> In this particular context, a try/catch is fine. However as a general rule we should avoid try/catch when possible. While Node 6 and above successfully handle the performance implications of try/catch there are other points to be aware of. See [How to know when (not) to throw](http://www.nearform.com/nodecrunch/10-tips-coding-node-js-3-know-throw-2/) for more details.
870
880
871
881
If the file does not exist, we call our `makeIt` function.
872
882
@@ -891,13 +901,14 @@ function makeIt() {
891
901
This achieve the same result, but directly manages the file handle (an OS-level reference to the file).
892
902
893
903
We use `fs.openSync` to create the file and get a file descriptor (`fd`),
894
-
then instead of fs.chmodSync and fs.chownSync both of which expect a file
904
+
then instead of `fs.chmodSync` and `fs.chownSync` both of which expect a file
895
905
path, we use `fs.fchmodSync` and `fs.fchownSync` which take a file descriptor.
896
906
897
907
898
908
### See also
899
909
900
-
* TODO
910
+
**Watching files and directories* in this chapter
911
+
**Receiving POST Data* in **Chapter 5 Wielding Web protocols**
901
912
902
913
## Watching files and directories
903
914
@@ -929,7 +940,7 @@ We'll also create a file to watch:
929
940
$ echo"some content"> my-file.txt
930
941
```
931
942
932
-
Finally we want to create a file called `watcher.js` (inside the `watching-files-and-directories` folder) and open it in our favourite editor.
943
+
Finally we want to create a file called `watcher.js` (inside the `watching-files-and-directories` folder) and open it in our favorite editor.
933
944
934
945
### How to do it
935
946
@@ -945,7 +956,7 @@ Next we'll set up some references:
945
956
```js
946
957
constinterval=5007
947
958
constfile=process.argv[2]
948
-
let exists =false
959
+
var exists =false
949
960
```
950
961
951
962
Do a quick check to make sure we've been supplied a file:
@@ -1166,11 +1177,12 @@ mkdir my-subfolder
1166
1177
1167
1178
### See also
1168
1179
1169
-
*Chapter 2, Fetching Metadata
1170
-
*TODO - more
1180
+
**Fetching meta-data* in this chapter
1181
+
**Setting up a development environment* in **Chapter 10 Building Microservice systems**
1171
1182
1172
1183
1173
1184
## Communicating over sockets
1185
+
1174
1186
One way to look at a socket is as a special file. Like a file it's a readable and writable data container. On some Operating Systems network sockets are literally a special type of file whereas on others the implementation is more abstract.
1175
1187
1176
1188
At any rate, the concept of a socket has changed our lives because it allows
@@ -1181,7 +1193,7 @@ In this recipe we'll build a TCP client and server.
1181
1193
### Getting Ready
1182
1194
1183
1195
Let's create two files `client.js` and `server.js` and open them in our
1184
-
favourite editor.
1196
+
favorite editor.
1185
1197
1186
1198
### How to do it
1187
1199
@@ -1294,7 +1306,7 @@ Let's learn a little more about sockets, and the different types of sockets that
1294
1306
#### `net` sockets are streams
1295
1307
1296
1308
Previous recipes in this chapter have alluded to streams,
1297
-
we'll be studying these in depth in **Chapter 3 Using Streams**.
1309
+
we'll be studying these in depth in **Chapter 4 Using Streams**.
1298
1310
1299
1311
However we would be remiss if we didn't mention that TCP sockets
1300
1312
implement the streams interface.
@@ -1440,13 +1452,12 @@ We'll notice that the server (like the client) no longer listens for a `close` e
1440
1452
this is because the sockets are bound to different ports so there's not way
1441
1453
(without a higher level protocol like TCP) of triggering a close from the other side.
1442
1454
1455
+
1443
1456
### See also
1444
1457
1445
-
* TODO
1446
-
* Interfacing with standard I/O
1447
-
* making clients and servers chapter
1448
-
* streams chapter?
1449
-
* wielding express
1450
-
* getting hapi
1451
-
* microservices chapter?
1458
+
**Interfacing with standard I/O* in this chapter
1459
+
**Setting up a development environment* in **Chapter 10 Building Microservice systems**
1460
+
**Using the pipe method* in **Chapter 4 Using Streams**
1461
+
**Decoupling I/O* in **Chapter 4 Using Streams**
1462
+
**Pattern Routing* in the *There's More* section of *Standardizing service boilerplate* in **Chapter 10 Building Microservice Systems**
0 commit comments