Node.js Basics
Updated: 03 September 2023
Basic Modules
Installing Prerequisites
Installing NodeJs
Install the necessary version of Node Node v8+ and NPM v5+
Confirm that node is installed
1node -v2npm -v
Also installing a node server globally
1npm i -g node-static
Installing MongoDb
Install Mongo from the Download page
Confirm that MongoDb is installed
1mongod --version
How start a Node REPL environment
Can run standard javascript with
1node
Alternatively, we can use eval with
1node -e "<javascript code>"
To run a node script we use
1node file.js
This can be an absolute or releative path to the file
NodeJs Globals
We are providded with some additional objects and keywords on top of javascript
global
process
module.exports
orexports
Global
Any first level global
property is available without the keywords Some poperties of the global object are as follows:
process
require
module
console
__dirname
__filename
Processes
Every Node.js script is a process
We can interact with the process by:
env
Enviromnent variablesargv
Command-line argumentsexit()
Terminate the current process
Process exit codes can be specified
1// process failed2process.exit(1)3
4// process exited successfully5process.exit(0)6
7// process failed with custom exit code8process.exit(code)
Import and Export Modules
module.exports
Global property to allow a script to export something for other modules to use
1module.exports = function (numbersToSum) {2 let sum = 0,3 i = 0,4 l = numbersToSum.length5 while (i < l) {6 sum += numbersToSum[i++]7 }8 return sum9}
require
require() is a path to a file, or a name. This will import the necessary files that we need to read. JSON files can be imported directly as an object.
1const sum = require('./utility.js')
require can be used to import many types of modules as such:
1const filesystem = require('fs') // core module2const express = require('express') // npm module3const server = require('./boot/server.js') // server.js file with a relative path down the tree4const server = require('../boot/server.js') // server.js file with a relative path up the tree5const server = require('/var/www/app/boot/server.js') // server.js file with an absolute path6const server = require('./boot/server') // file if there's the server.js file7const routes = require('../routes') // index.js inside routes folder if there's no routes.js file8const databaseConfigs = require('./configs/database.json') // JSON file
Core Modules
Node has a lot of preinstalled modules, the main ones are as follows:
- fs: module to work with the file system, files and folders
- path: module to parse file system paths across platforms
- querystring: module to parse query string data
- net: module to work with networking for various protocols
- stream: module to work with data streams
- events: module to implement event emitters (Node observer pattern)
- child_process: module to spawn external processes
- os: module to access OS-level information including platform, number of CPUs, memory, uptime, etc.
- url: module to parse URLs
- http: module to make requests (client) and accept requests (server)
- https: module to do the same as http only for HTTPS
- util: various utilities including promosify which turns any standard Node core method into a promise-base API
- assert: module to perform assertion based testing
- crypto: module to encrypt and hash information
fs
Handles file system operations
- fs.readFile() reads files asynchronously
- fs.readFileSync() reads files synchronously
- fs.writeFile() writes files asynchronously
- fs.writeFileSync() writes files synchronously
Reading a File
1const fs = require('fs')2const path = require('path')3fs.readFile(4 path.join(__dirname, '/data/customers.csv'),5 { encoding: 'utf-8' },6 function (error, data) {7 if (error) return console.error(error)8 console.log(data)9 }10)
Writing to a file
1const fs = require('fs')2fs.writeFile('message.txt', 'Hello World!', function (error) {3 if (error) return console.error(error)4 console.log('Writing is done.')5})
path
Can join a path relativley as:
1const path = require('path')2const server = require(path.join('app', 'server.js'))
Or absoltely as:
1const path = require('path')2const server = require(path.join(__dirname, 'app', 'server.js'))
Event emitters
We can create an EventEmitter with events
and using this we can create, listen and trigger events
Single trigger
1const EventEmitter = require('events')2
3class Job extends EventEmitter {}4job = new Job()5
6job.on('done', function (timeDone) {7 console.log('Job was pronounced done at', timeDone)8})9
10job.emit('done', new Date())11job.removeAllListeners() // remove all observers
Output Job was pronounced done at ____________
Mutiple triggers
1const EventEmitter = require('events')2
3class Emitter extends EventEmitter {}4emitter = new Emitter()5
6emitter.on('knock', function() {7 console.log('Who's there?')8})9
10emitter.on('knock', function() {11 console.log('Go away!')12})13
14emitter.emit('knock')15emitter.emit('knock')
Output
1Who's there?2Go away!3Who's there?4Go away!
Single Execution of Handler
1const EventEmitter = require('events')2
3class Emitter extends EventEmitter {}4emitter = new Emitter()5
6emitter.once('knock', function() {7 console.log('Who's there?')8})9
10
11emitter.emit('knock')12emitter.emit('knock')
Output Who's there?
Modular events
We can use the observer pattern to modularize code. This allows us to customize modular behaviour without modifying the module.
jobs.js
1const EventEmitter = require('events')2class Job extends EventEmitter {3 constructor(ops) {4 super(ops)5 this.on('start', () => {6 this.process()7 })8 }9 process() {10 setTimeout(() => {11 // Emulate the delay of the job - async!12 this.emit('done', { completedOn: new Date() })13 }, 700)14 }15}16
17module.exports = Job
main.js
1var Job = require('./job.js')2var job = new Job()3
4job.on('done', function (details) {5 console.log('Weekly email job was completed at', details.completedOn)6})7
8job.emit('start')
HTTP Client
Get
Request and Response
Making an HTTP Request using http from NodeJs Core. Will receive data in chunks as follows http-get-no-buff
1const http = require('http')2const url = 'http://nodeprogram.com'3http4 .get(url, (response) => {5 response.on('data', (chunk) => {6 console.log(chunk.toString('utf8'))7 })8 response.on('end', () => {9 console.log('response has ended')10 })11 })12 .on('error', (error) => {13 console.error(`Got error: ${error.message}`)14 })
Alternatively, the data can be aded to a buffer until the response is complete as below http-get.js
1const http = require('http')2const url = 'http://nodeprogram.com'3http4 .get(url, (response) => {5 let rawData = ''6 response.on('data', (chunk) => {7 rawData += chunk8 })9 response.on('end', () => {10 console.log(rawData)11 })12 })13 .on('error', (error) => {14 console.error(`Got error: ${error.message}`)15 })
Processing JSON
In order to get JSON the full response is needed, after which we parse the json to a response object
http-json-get.js
1const https = require('https')2const url =3 'https://gist.githubusercontent.com/azat-co/a3b93807d89fd5f98ba7829f0557e266/raw/43adc16c256ec52264c2d0bc0251369faf02a3e2/gistfile1.txt'4https5 .get(url, (response) => {6 let rawData = ''7 response.on('data', (chunk) => {8 rawData += chunk9 })10 response.on('end', () => {11 try {12 const parsedData = JSON.parse(rawData)13 console.log(parsedData)14 } catch (e) {15 console.error(e.message)16 }17 })18 })19 .on('error', (error) => {20 console.error(`Got error: ${error.message}`)21 })
Post
To do a post we require a little but more information to be configured as such:
http-post.js
1const http = require('http')2const postData = JSON.stringify({ foo: 'bar' })3
4const options = {5 hostname: 'mockbin.com',6 port: 80,7 path: '/request?foo=bar&foo=baz',8 method: 'POST',9 headers: {10 'Content-Type': 'application/x-www-form-urlencoded',11 'Content-Length': Buffer.byteLength(postData),12 },13}14
15const req = http.request(options, (res) => {16 res.on('data', (chunk) => {17 console.log(`BODY: ${chunk}`)18 })19 res.on('end', () => {20 console.log('No more data in response.')21 })22})23
24req.on('error', (e) => {25 console.error(`problem with request: ${e.message}`)26})27
28req.write(postData)29req.end()
HTTP Server
We can use node http-server.js
to run the server, we can also use node-dev
to run the server and refresh on filechange.
http-server.js
1const http = require('http')2const port = 30003http4 .createServer((req, res) => {5 res.writeHead(200, { 'Content-Type': 'text/plain' })6 res.end('Hello World\n')7 })8 .listen(port)9
10console.log(`Server running at http://localhost:${port}/`)
http.createServer
creates a server with a callback function which contains a response handler code
res.writeHead(200, {'Content-Type': 'text/plain'})
sets the right status code and headers
res.end()
event handler for when response is complete
listen()
specifies the port on which the server is listening
Processing a request
We can process an incoming request by reading the request properties with the following:
httP-server-request-processing.js
1const http = require('http')2const port = 30003http.createServer((request, response) => {4 console.log(request.headers)5 console.log(request.method)6 console.log(request.statusCode)7 console.log(request.url)8 if (request.method == 'POST') {9 let buff = ''10 request.on('data', function (chunk) {11 buff += chunk12 })13 request.on('end', function () {14 console.log(`Body: ${buff}`)15 response.end('\nAccepted body\n')16 })17 } else {18 response.writeHead(200, {'Content-Type': 'text/plain'})19 response.end('Hello World\n')20 }21}).listen(port)