events ModuleNode.js has an EventEmitter class that can be accessed by importing the events core module. Each event emitter instance has an .on() method that assigns a listener callback function to a named event. EventEmitter also has an .emit() method, which announces that a named event has occurred.
// Require in the 'events' core modulelet events = require('events');// Create an instance of the EventEmitter classlet myEmitter = new events.EventEmitter();let showNewUser = (data) => {console.log(`participant: ${data}.`);};// Assign the showNewUser function as the listener callback for 'new user' eventsmyEmitter.on('new user', showNewUser)// Emit a 'new user' eventmyEmitter.emit('new user', 'Lily Pad') // Prints: participant: Lily Pad.
error ModuleMany asynchronous Node.js APIs assume that the provided callback function will have an error passed as the first argument, followed by the resulting data of a (successful) operation. If the asynchronous task results in an error, the error will be passed in as the first argument to the callback function, with no second argument. If no error was thrown, then the first argument will be undefined, and the resulting data of the operation will be passed as the second argument.
Input is data that is given to the computer, while output is any data or feedback that a computer provides. In Node, we can get input from a user using the stdin.on() method on the process object. We are able to use this because process.stdin is an instance of EventEmitter. To give an output, we can use the stdout.write() method on the process object as well. This is because console.log() is actually a thin wrapper on stdout.write().
// recieve an inputprocess.stdin.on('data', onDataCallback);// produce an outputprocess.stdout.write(data);
fs ModuleThe file system controls how data on a computer is stored and retrieved. Node.js provides the fs core module, which allows interaction with the file system. Each method provided through the module has synchronous and asynchronous versions to allow for flexibility. One method available in the module is .readFile(), which reads data from the provided file.
const fs = require('fs');// First argument is the file path// The second argument is the file’s character encoding// The third argument is an error-first callback functionfs.readFile('./file.txt', 'utf-8', callbackFunction);
In most cases, data is not processed all at once, but rather piece by piece, which we call a stream. Streaming data is preferred as it doesn’t require tons of RAM and doesn’t need to have all the data on hand to begin processing it. To read files line by line, we can use the .createInterface() method from the readline core module in conjunction with fs.createReadStream(). We can create a writeable stream by using the fs.createWriteStream() method, and write to the stream using .write().
const fs = require('fs');const readline = require('readline');// Readable streamreadline.createInterface({input: fs.createReadStream('text.txt')});// Writable Streamconst writableStream = fs.createWriteStream('output.txt');writableStream.write('data');writableStream.close();
Buffer ObjectA Buffer is an object that represents a static amount of memory that cannot be resized. The Buffer class is within the buffer module. Although this module is globally available, the Node.js documentation still recommends explicitly importing Buffer.
const { Buffer } = require('buffer');const myBuffer = Buffer.from('Hello World!');
.alloc() MethodThe Buffer object has the .alloc() method, which creates a new Buffer object with the size specified by the first argument. Optionally, a second argument can be provided to specify the fill, and a third argument to specify the character encoding.
// Creates a buffer of size 10 filled with 'b'// character encoding utf-8 by default// 'b' is represented by 62 in hexconst bufferAlloc = Buffer.alloc(10, 'b'); // <Buffer 62 62 62 62 62 62 62 62 62 62>
.toString() MethodA Buffer object can be translated into a human-readable string by chaining the .toString() method to a Buffer object. Optionally, encoding can be specified as the first argument, byte offset to begin translating can be provided as the second argument, and the byte offset to end translating as the third argument.
const bufferAlloc = Buffer.alloc(5, 'b');console.log(bufferAlloc.toString()); // Ouptut: bbbbb
.from() MethodA new Buffer object can be created from a specified string, array, or another Buffer object using the .from() method. Optionally, a character encoding can be specified as the second argument, defaulting to 'utf-8'.
// Creates buffer from the string 'Hello World'const bufferFrom = Buffer.from('Hello World');console.log(bufferFrom); // <Buffer 48 65 6c 6c 6f 20 57 6f 72 6c 64>
.concat() MethodThe .concat() method takes an array of Buffer objects and joins them all into a single, new Buffer object. This comes in handy because a Buffer object cannot be resized.
Optionally, the length of the concatenated buffer may be explicitly specified as the second argument. If the length of the result is greater than the specified total length, it is truncated. If the actual length is less than the specified total length, the remaining bytes are filled with zeroes.
const buffer1 = Buffer.from('Hello');const buffer2 = Buffer.from('World');const bufferArray = [buffer1, buffer2];const combinedBuffer = Buffer.concat(bufferArray);console.log(combinedBuffer.toString()); // Logs 'HelloWorld'
timers ModuleThe global timers module contains scheduling functions such as setTimeout(), setInterval(), and setImmediate(). These functions place tasks into queues, which are processed at every iteration of the Node.js event loop.
setImmediate() FunctionThe setImmediate() function executes the specified callback function after the current poll phase of the event loop has completed. The function accepts a callback function as its first argument and optionally accepts additional arguments that will be passed to the callback.
setImmediate(() => {console.log('End of the poll phase!');})