NodeJS Tutorial Notes.
NodeJS Tutorial Notes.
Table of Contents
NodeJS Tutorial
Global Variables in NodeJS
Modularizing Code
Built-in Modules
os module
path module
fs module
> 65
65
> _
65
_ + 3
68
> "a"
'a'
> _
'a'
>
__filename - filename
Modularizing Code
TOC
CommonJS, every file is module (by default)
Modules - Encapsulated Code (only share minimum)
const secret = 'SUPER SECRET'
const john = 'john'
const peter = 'peter'
sayHi('susan')
// sayHi(names.john)
// sayHi(names.peter)
const sayHi = require('./05-utils') /*here the nae of the variable should be only
sayHi
As only single item is added in module.exports and it is added directly and not in
object.*/
sayHi('susan')
sayHi(names.john)
sayHi(names.peter)
/*On doing */ console.log("03: ", bake, '\n', sayHi, '\n', data); /*see output*/
// local
const secret = 'SUPER SECRET' /*Note that since `secret is not exported hence it is
not excessible outside of this file`*/
// share
const john = 'john'
const peter = 'peter'
const num1 = 5
const num2 = 10
function addValues() {
console.log(`07: \nthe sum is : ${num1 + num2}`)
}
addValues()
/*Note that on importing the file in 3-modules.js file we are actually only running
the Code,
bcoz at the end of this file we are calling the function `addValues()`*/
Built-in Modules
TOC
os module
const os = require('os')
const currentOS = {
name: os.type(),
release: os.release(),
totalMem: os.totalmem(),
freeMem: os.freemem(),
}
console.log('currentOS: \n', currentOS)
Windows 10.
Linux:
path module
Allows access to file paths
const path = require('path')
console.log(path.sep)
/* returns platform specific seperator
* for windows it's '\'
* linux '/'
**/
console.log('======\nI don\'t know why I\'m doing this but i\'m doing it. I am
making a new file');
writeFileSync('./tut64_sample/nayka.txt', `maine ye ku likha mujhe pata nhi`, 'utf-
8')
note: I don't know why but file 10-fs-sync.js didn't worked for me.
It was not running bcoz I was in the node-express-course , it'll work if I go to 01-node-tutorial folder, perhaps
because it is an npm folder.
console.log('*.*.*.*.*.*.*.*.*.*.*\n Appending to a file');
writeFileSync("./tut64_sample/nayka.txt",
'\nइस file का नाम नयका है',
{ flag: 'a' }
)
console.log('Appending done check =>
`./tut64_sample/nayka.txt`\n*.*.*.*.*.*.*.*.*.*.*\n');
/**I'll be reading from two files a.txt & b.txt and writing them into
res_fs_async.txt */
Output:
✨🕸🔥🎆🎇
---Synchronous or Blocking---
Line by line execution.
readFileSync() opeation synchronously reads the file and execution of the next line of code is not done
until the reading of the current file is not done
example:
const fs = require("fs");
let text = fs.readFileSync("exp.txt", "utf-8");
console.log("the content of the file is:");
console.log(text);
output:
✨🕸🔥🎆🎇
--- Asynchronous or non-Blocking ---
line by line execution not guranteed.
callbacks will fire after the Asynchronous block of code.
जब हम Asynchronous code लिखते है तब वो background मे चलता रहता है जबतक वो अपना पुरा execution नही कर
लेता.
और till the time being उस Asynchronous block of code के बाद जो code hai wo run करता रहेगा.
जब भी Asynchronous block of code का execution हो जायेगा तब उसका callback function fire होगा.
CODE IS ALWAYS EXECUTED LINE-BY-LINE!!!
but यहा ऐसा प्रतित होता है की code line-by-line execute नही होता है.
example:
let text2 = fs.readFile("exp.txt", "utf-8", (err, data) => {
//a call-back function is required by readFile()
//readFile is asynchronous function
console.log(data);
});
console.log("this is a message");
Output:
server.listen(5000)// the server will listen to all the requests at port no.:5000
Output :
1.
const http = require("http")
const server = http.createServer((req, res) => {
console.log(req.url);
if (req.url === '/') {
res.write('welcome to our home page')
res.end()
}
if (req.url === '/about') {
res.end('about page')
}
/**res.write('welcome to our home page');
* res.end();
* I had not removed this part earlier and it was showing error for some reason
*/
})
server.listen(5000)
Using lowdash :
Note that the commands should be npm start or npm run start but for dev it should i=only be npm run dev
Installing package globally : npm install -g nodemon
Now the command nodemon app.js works properly
Better to set up these kinds of dependencies locally in devDependencies or use npx , Installing them globally
may sometime give errors
package-lock.json contains details( such as version) of dependencies की dependencies
Event Loop
TOC
NodeJS Event Loop
It explains how Node.js can be asynchronous and have non-blocking I/O.
The Node.js JavaScript code runs on a single thread. There is just one thing happening at a time.
This is a limitation that's actually very helpful, as it simplifies a lot how you program without worrying about
concurrency issues.
Synchronous JS: Blocking JS
↓
Asynchronous JS: Non-Blocking
↓
Every time there is some Asynchronous Code it's gonna be ofloaded and it is executed only when the tast is
completed
const http = require('http')
const server = http.createServer((req, res) => {
console.log('request event')
res.end('Hello World')
})
server.listen(5000, () => {
console.log('Server listening on port : 5000....')
})
Note that the server.listen() function is asynchronous and the Event Loop is waiting for the requests and
responding to it
Example : Effect of a blocking code on different requests
const http = require('http')
Everything is Good
const http = require('http')
Everything is not good and all the requests are blocked because of a single Blocking Code:
Async Patterns
TOC
JavaScript Promises
const getFile = (path) => {
/**This is our Wrapper function */
return new Promise((resolve, reject) => {
/** "Producing Code" (May take some time) */
readFile(path, 'utf-8', (err, data) => {
if (err) {
reject(err) // when error
}
else {
resolve(data) // when successful
}
})
})
}
/* Method-1 */
getFile('./tut64_sample/a.txt')
.then(function (result) {
//this is success function
console.log(result)
})
.catch((err) => {
//this is error function
console.log(err);
})
/* --------end----Method-1------- */
// ---------OR---------
/* -------Method-2------- */
getFile('./tut64_sample/a.txt').then(
(result) => console.log(result)
,
(err) => console.log(err)
)
/* --------end----Method-3------- */
// -----------OR------------
/* ---------Method-3------- */
const start = async () => {
// reading both first and second file in sequence
try {
const first = await getText('./tut64_sample/a.txt')
const second = await getText('./tut64_sample/b.txt')
console.log(first, '-------', second);
} catch (error) {
console.log(error);
}
}
start()
/* --------end----Method-3------- */
Alternative to 11-fs-async.js :
Using module util
const { readFile, writeFile } = require("fs");
const util = require('util')
const readFilePromise = util.promisify(readFile)
const writeFilePromise = util.promisify(writeFile)
const start = async () => {
try {
const first = await readFilePromise('./tut64_sample/a.txt', 'utf-8')
const second = await readFilePromise('./tut64_sample/b.txt', 'utf-8')
console.log(first, '-------', second);
await writeFilePromise('./tut64_sample/result_a_b.txt',
`\n----now-appending----This the result of util module: \n first:
${first}\nsecond: ${second}`,
{ flag: 'a' })
} catch (error) {
console.log(error);
}
start()
start()
Final O/p:
Events Emitter
TOC
Event Driven Programming in Node JS
Event Driven Programming : a style in which the flow of the program is at least in part determined by the
events that occur as the program executes.
ex : in BrowserJS it could be like : on button click do something, on mouse hover do something.
The idea is like:
1. we listen for specific events &
2. register functions that will execute in response to those events.
3. Once our events takes place callback function fires up.
event module
customEvent.emit('response')
customEvent.emit('response')
The order matters while we are writing on() & emit() functions on() functions should always be above the
emit() function.
customEvent.emit('response')
customEvent.on('response', () => {
console.log(`response data received`);
})
customEvent.on('response', () => {
console.log(`some other logic here`);
})
Because i first emit the event and only then i listen for it. This doesn't makes sense
const EventEmitter = require('events');
we go with http.createServer() and then we pass in this callback function and then of course this callback
function will be invoked every time someone visits our server.
We can use EventEmitter API to setup the server
instead of passing in the callback function we will do the following:
const http = require('http')
server.listen(5000)
I have created a file 0-big.txt of file size 165KB. And to read that file we will be using createReadStream()
function
// Creating 0-big.txt
const { writeFileSync } = require('fs')
for (let i = 0; i < 10000; i++) {
writeFileSync('0-big.txt', `hello world ${i}\n`, { flag: 'a' })
}
O/P:
Notice that we are reading the data in multiple chunks in of 65486 Bytes i.e., 64KB
A readStream is created when we use createReadStream() and invoke it
Instances of class <fs.ReadStream> are created and returned using the fs.createReadStream() function.
Class fs.ReadStream extends <stream.Readable>
For streams that are not operating in object mode, the chunk will be either a string or Buffer
For streams that are in object mode, the chunk can be any JavaScript value other than null.
Default size of Buffer 64KB. To change the buffer size we can do:
const { createReadStream } = require("fs")
the O/p seems in text bcoz the encoding is utf8 or else it would be like the o/p in above Screenshot.
const { createReadStream } = require("fs")
1.
2.
Code 2 : Sending data in chunks :
var http = require('http')
var fs = require('fs')
http
.createServer(function (req, res) {
// const text = fs.readFileSync('./content/big.txt', 'utf8')
// res.end(text)
const fileStream = fs.createReadStream('./content/big.txt', 'utf8')
fileStream.on('open', () => {
fileStream.pipe(res)
})
fileStream.on('error', (err) => {
res.end(err)
})
})
.listen(5000)
pipe() method is used to push data from ReadStream to WriteStream . It hepls in writing data in chunks
the memory used up is same but it is better as it is chunked
HTTP Requests
TOC
The general structure for both messages is similar they both have a start line,
both have optional headers (a blank line indicating that all the meta info has
been sent and effectively headers are that meta info) & an optional body
Request messages are what the user is sending.
Request Message:
When the user is requesting something & it just want the resource then there is no body.
If we want to add a resource to the server then we need to provide that data (payload)
Response Message:
In header we provide info about our res. msg.
GET is the default request made by the browser
in POST request we have to send some payload in the http url
in Headers we provide info. about Response/Request message.
so you go into the browser you request a resource (by default it is a get request) and then in that body when the
server sends the html of the site .
Setting Up Servers
TOC
http is built-in module
In computer networking, a port is a communication endpoint
At software level withi an OS a port is a logical construct that identifies a specific process or a type of network
service.
Wikipedia- Port (computer networking)
Notable well-known port numbers
Number Assignment
20 File Transfer Protocol (FTP) Data Transfer
21 File Transfer Protocol (FTP) Command Control
22 Secure Shell (SSH) Secure Login
23 Telnet remote login service, unencrypted text messages
25 Simple Mail Transfer Protocol (SMTP) email delivery
53 Domain Name System (DNS) service
67, 68 Dynamic Host Configuration Protocol (DHCP)
80 Hypertext Transfer Protocol (HTTP) used in the World Wide Web
110 Post Office Protocol (POP3)
119 Network News Transfer Protocol (NNTP)
123 Network Time Protocol (NTP)
143 Internet Message Access Protocol (IMAP) Management of digital mail
161 Simple Network Management Protocol (SNMP)
194 Internet Relay Chat (IRC)
443 HTTP Secure (HTTPS) HTTP over TLS/SSL
server.listen(5000)
If we visit the website from the browser i.e. user has hit the server but the browser will continue to wait for the
response until and unless it receives some response
The method response.end() should always be used in order to provide some response to the browser
That method must be called on each response
1. We aren't providing any meta data about the body that we're sending back
2. localhost:5000/xyz is alse sending same response as localhost:5000
res.writeHead() to provide header and status code: header is object by which browser knows what to do with
the response received
200 it's statusCode
{'content-type': 'text/html' } is a MIME Type it tells browser that I am sending HTML , CSS , or Image
server.listen(5000)
O/P:
and for the following MIME Type:
res.writeHead(200, { 'content-type': 'text/plain' })
O/P:
HTTP response status codes- moz://a
MIME types (IANA media types) - moz://a
request object
res.method : Tells what kind of request it is i.e., GET, POST,...
res.url : user is trying to access the resource by the name of /blah_blah_blah or just /
Setting Up Server
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Home Page</h1>
<h4>नमसकरम् पृथ्वी</h4>
</body>
</html>
const http = require('http')
const { readFileSync } = require('fs')
const homePage = readFileSync('./index.html')
/**we are using readFileSync here because we are reading the file only once
* i.e., only at the start of the server */
const server = http.createServer((req, res) => {
console.log('user hit the server');
const url = req.url
console.log(req.method);
console.log(req.url);
server.listen(5000)
Note that if I go with the link localhost:5000/about/xyz or localhost:5000/about then it'll also br 404
Serving the navbar-app
The Problem:
Normally the look of the navbar-app is :
after changing the above code as : const homePage = readFileSync('./navbar-app/index.html')
Observation:
The following end points are being requested:
that is we will have to read and serve the style.css , logo , javascript as well
Pretty Big Server code
const http = require('http')
const { readFileSync } = require('fs')
const homePage = readFileSync('./navbar-app/index.html')
const homeStyle = readFileSync('./navbar-app/styles.css')
const homeImage = readFileSync('./navbar-app/logo.svg')
const homeLogic = readFileSync('./navbar-app/browser-app.js')
// we are using sync here because we are reading the file only once i.e., only at
the start of the server
const server = http.createServer((req, res) => {
// console.log('user hit the server');
const url = req.url
// console.log(req.method);
console.log(req.url);
server.listen(5000)
O/P:
Express.js
TOC
ExpressJS
ExpressJS is built on top of node http module.
const express = require('express')
const app = express() // <- this line will give us a server instance
//or
// const app = require('express')()
app.listen(5000, () => {
// when we will instantiate the server we will run this function
console.log('server is listening on port 5000');
})
/*
app.get()
app.post()
app.put()
app.delete()
app.all()
app.use()
app.listen()
*/
// use() is for middleware
app.listen(5000, () => {
console.log('server is listening on port 5000');
})
app.listen(5000, () => {
console.log('server is listening to port 5000.... ');
})
Note that inside ./navbar-app/index.js the location of css & js files are mentioned as :
...
<!-- styles -->
<link rel="stylesheet" href="./styles.css" />
</head>
...
<!-- javascript -->
<script src="./browser-app.js"></script>
</body>
static asset = the assets that the server doesn't need to change like: images, css, js file(s)
In http module to serve a image we have to set and endpoing for every single static File
In express we can just set it up by placing them all in ./public folder and dump all assets there.
There are two ways of serving the index.html file:
1. dumping it into ./public folder
2. using SSR
method 1 does work properly
const path = require('path')
const express = require('express')
const app = express()
app.listen(5000, () => {
console.log('server is listening to port 5000.... ');
})
when it comes to express in most cases you'll use one of the two following options you'll use it to set up API or
templates with server side rendering
API Vs SSR
TOC
API
In http case when we talk about API we mean setting up an http interface to interact with our data. Data is
sent using JSON using res.json()
SSR
In server side rendering where we will set up templates and send back entire html, css and javascript
ourselves using res.render()
Setting Up API
TOC
res.json([body])
Sends a JSON response. This method sends a response (with the correct content-type & statusCode) that is the
parameter converted to a JSON string using JSON.stringify() by default.
Basic API Setup:🎉 🥳 🎊
const express = require('express')
const app = express()
app.listen(5000, () => {
console.log('server listening to port 5000');
})
const products = [
{
id: 1,
name: 'albany sofa',
image:
'https://dl.airtable.com/.attachments/6ac7f7b55d505057317534722e5a9f03/9183491e/pro
duct-3.jpg',
price: 39.95,
desc: `I'm baby direct trade farm-to-table hell of, YOLO readymade raw denim
venmo whatever organic gluten-free kitsch schlitz irony af flexitarian.`,
},
{
id: 2,
name: 'entertainment center',
image:
'https://dl.airtable.com/.attachments/da5e17fd71f50578d525dd5f596e407e/d5e88ac8/pro
duct-2.jpg',
price: 29.98,
desc: `I'm baby direct trade farm-to-table hell of, YOLO readymade raw denim
venmo whatever organic gluten-free kitsch schlitz irony af flexitarian.`,
},
{
id: 3,
name: 'albany sectional',
image:
'https://dl.airtable.com/.attachments/05ecddf7ac8d581ecc3f7922415e7907/a4242abc/pro
duct-1.jpeg',
price: 10.99,
desc: `I'm baby direct trade farm-to-table hell of, YOLO readymade raw denim
venmo whatever organic gluten-free kitsch schlitz irony af flexitarian.`,
},
{
id: 4,
name: 'leather sofa',
image:
'https://dl.airtable.com/.attachments/3245c726ee77d73702ba8c3310639727/f000842b/pro
duct-5.jpg',
price: 9.99,
desc: `I'm baby direct trade farm-to-table hell of, YOLO readymade raw denim
venmo whatever organic gluten-free kitsch schlitz irony af flexitarian.`,
},
]
const people = [
{ id: 1, name: 'john' },
{ id: 2, name: 'peter' },
{ id: 3, name: 'susan' },
{ id: 4, name: 'anna' },
{ id: 5, name: 'emma' },
]
module.exports = { products, people }
app.listen(5000, () => {
console.log('server listening to port 5000');
})
Instead of sending everything in the API we can send some specefic items
const express = require('express')
const app = express()
const { products, people } = require("./data.js")
app.get('/', (req, res) => {
// res.json(products)
res.send('<h1>Home Page</h1> <a href="/api/products">products</a>')
})
app.get('/api/products', (req, res) => {
// res.json(products)
// sending products without the `desc` key
const newProducts = products.map((product) => {
const { id, name, image, price } = product
return { id, name, image, price }
})
res.json(newProducts)
})
app.listen(5000, () => {
console.log('server listening to port 5000');
})
Route Parameters
TOC
→ Setting server so that from the site localhost:5000/api/products/1 I'll get info. only about the first
product ←
app.get('/api/products/:productID', (req, res) => {
console.log(req.params);
const { productID } = req.params
const singleProduct = products.find((product) => product.id ===
Number(productID))
// I was using filter earlier which was returning empty array if the id didn't
exist so I was not getting 404
/*find can also be written as :
const singleProduct = products.find((product) => {
if (product.id === Number(productID))
return product;
})
*/
if (singleProduct) {
return res.json(singleProduct)
//app.get() is basically a function so I can write return here but,
// Note that it was sending `res.send()` or `res.json()` if return was not
written
// but If return was not written then the line next to it was also executed
}
return res.status(404).send('Resource Not Found')
})
Console:
Note that in code productID is the param which we are passing to the server
productID is received as a string
Complex Route Parameters
app.get('/api/products/:productID/reviews/:reviewID', (req, res) => {
console.log(req.params);
res.send("नमस्ते दुनीया")
})
Also note that the param from the previous Route is also printed because that route was also present in this route.
Query String Parameter
query string parameters or url parameters is way for to send small amounts of information to the server
this information is usually used as parameters to for example query database or filter results
app.get('/api/query', (req, res) => {
console.log(req.query);
res.send("नमस्ते दुनीया")
})
note that → query?name=adarsh&title=singh&age=21 ← after query there is ? after which the query
parameter is written and we can continue to write as many query parameter as we like
Example : Using Query String to filter data
app.get('/api/query', (req, res) => {
let sortedProducts = [...products]
const { search, limit } = req.query;
if (search) {
sortedProducts = sortedProducts.filter((product) => {
return product.name.startsWith(search)
})
}
if (limit) {
sortedProducts = sortedProducts.slice(0, Number(limit))
}
if (sortedProducts.length < 1) {
// return res.status(200).send("no products found")
// or the below way is a more common way of sending these kind of responses
return res.status(200).send({ success: true, data: [] })
}
return res.json(sortedProducts)
})
Note that if i provide the query parms donot match then all the products will be returned
http://localhost:5000/api/query?search=a&limit=1
http://localhost:5000/api/query?search=a
http://localhost:5000/api/query? or http://localhost:5000/api/query
All Products are displayed
http://localhost:5000/api/query?limit=2
Errors: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
you cannot send two responses in the same request one after the another.
to avoid these kind of errors always use return keyword while sending the responses
MiddleWares in ExpressJS
TOC
Middleware are functions that execute during the request to the server
Each Middleware function has access to both req , res objects
express provides some middleware functions.
req → middleware → res
res.send('Home')
})
like: →
When we are working with a middleware then we have to one of the two things:
1. we must pass it on to a next middleware , OR
2. we are terminating the whole, cycle by sending back a response
Example 1:
const logger = (req, res, next) => {
const method = req.method
const url = req.url
const time = new Date().getFullYear()
console.log(method, url, time);
we are passing to the next middleware here it is app.get('/', ...) which is sending back the final response
Example 2:
const logger = (req, res, next) => {
const method = req.method
const url = req.url
const time = new Date().getFullYear()
console.log(method, url, time);
next();
}
module.exports = logger
The middleware function will then work for any path that is after the /api
S.No. Route console
1 /
2 /about
3 /api/products
4 /api/items
Note : in ex 4 the route /api/items is wrong and in Browser we get
Cannot GET /api/asdfg but still since route present in app.use() is /api
hence, we will get the log in console as in image.
If path is omitted then the middleware is applied to all of the routes.
Using multiple middleware functions
TOC
mdware.js
app.js
Note that the order in which we write the middleware functions in the
list inside app.use([..]) is the oreder of their execution
const logger = require('./logger')
const authorize = require('./mdware')
app.use([mdware, logger])
One use Case of middleware : adding to req object from one route & accessing it from
anotehr route.
TOC
const mdware = (req, res, next) => {
const { user } = req.query;
if (user == "Adarsh") {
console.log("inside mdware\n user: ", user);
} else {
res.status(401).send("User Unauthorised");
}
}
module.exports = mdware;
app.use([mdware, logger])
app.listen(8430, () => {
console.log(`server listening to port 8430`);
})
S.No route Browser Server Console
1 /
2 /?user=Adarsh
3 /abt?
user=Adarsh
Now in any of my route I'll have access to that user because of mdware
Instead of adding multiple middlewares to all the routes we can also add them
only to some specefic routes like :
app.js
app.listen(8430, () => {
console.log(`server listening to port 8430`);
})
After this nothing will be shown in the home route but at About page we will get some console log depending upon
user value.
app.use(morgan('tiny'));
POST Method
TOC
Case 1 : POST request using HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./normalize.css" />
<link rel="stylesheet" href="./styles.css" />
<title>Traditional</title>
</head>
<body>
<nav>
<div class="nav-center">
<h5>HTTP Methods</h5>
<div>
<a href="index.html">regular </a>
<a href="javascript.html">javascript </a>
</div>
</div>
</nav>
<main>
<form action="/login" method="POST">
<h3>Traditional Form</h3>
<div class="form-row">
<label for="name"> enter name </label>
<input type="text" name="name" id="name" autocomplete="false" />
</div>
<button type="submit" class="block">submit</button>
</form>
</main>
</body>
</html>
Well now I have status 200 but I dont have access to whatever is being sent
In order to get the for data we will have to use
express.urlencoded() which will parse the data and add it to req.body built-in middleware as :
This is a built-in middleware function in Express. It parses incoming requests with urlencoded payloads
extended:true option allows parsing urlencoded data with query string library when it's false or the qs library
when true
After adding the code in app.js :
//parsing the body
app.use(express.urlencoded({ extended: false }))
Output :
app.use(morgan('tiny'));
app.use(express.static('./methods-public'));
console.log('"Invalid Credentials"');
res.status(404).send("Invalid Credentials")
})
app.listen(8430, () => {
console.log(`server listening to port 8430`);
})
Case 2 : POST request using JavaScript
TOC
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./normalize.css" />
<link rel="stylesheet" href="./styles.css" />
<title>Javascript</title>
</head>
<body>
<nav>
<div class="nav-center">
<h5>HTTP Methods</h5>
<div>
<a href="index.html">regular </a>
<a href="javascript.html">javascript </a>
</div>
</div>
</nav>
<main>
<section>
<form>
<h3>Javascript Form</h3>
<div class="form-row">
<label for="name"> enter name </label>
<input type="text" name="name" id="name" class="form-input"
autocomplete="false" />
<small class="form-alert"></small>
</div>
<button type="submit" class="block submit-btn">submit</button>
</form>
<div class="result"></div>
</section>
</main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.1/axios.min.js"
integrity="sha512-
bZS47S7sPOxkjU/4Bt0zrhEtWx0y0CRkhEp8IckzK+ltifIIE9EMIMTuT/mEzoIMewUINruDBIR/jJnbguo
nqQ=="
crossorigin="anonymous"></script>
<script>
const result = document.querySelector('.result')
try {
const inside_axios = await axios.post('/api/people', { name:
nameValue })
console.log(inside_axios);
</html>
1
app.use(morgan('tiny'));
app.use(express.static('./methods-public'));
// parsing json
app.use(express.json())
app.get('/api/people', (req, res) => {
res.status(200).json({ success: true, data: people })
})
app.listen(8430, () => {
console.log(`server listening to port 8430`);
})
console :
PUT Method
TOC
To edit some item in the backend we need to go with some route parameters like :
/api/people/:id
Here we will be sending the id in the route param & in the body we will send the value with wich update is to be
done
code for put:
app.put('/api/people/:id', (req, res) => {
const { id } = req.params;
const { name } = req.body;
console.log(id, name);
DELETE Method
TOC
url : localhost:8430/api/people/2 , here it doesn't matter if I keep a body here
because I will not be using it.
output :
{
"success": true,
"msg": "person with id: 2 deleted",
"data": [
{
"id": 1,
"name": "john"
},
{
"id": 3,
"name": "susan"
},
{
"id": 4,
"name": "anna"
},
{
"id": 5,
"name": "emma"
}
]
}
if (!person) {
return res.status(404).json({ success: false, msg: `no entry with id:
${req.params.id}` })
}
let newPeople = people.filter((person) => person.id !== Number(req.params.id))
return res.status(200).json(
{
success: true,
msg: `person with id: ${req.params.id} deleted`,
data: newPeople
})
})
inside _api_people.js :
The file _api_people.js will only take care of route /api/people/....
in that file change app to router
in app.js add these lines :
const _api_people = require("./routes/_api_people");
//setting up a middleware
app.use('/api/people', _api_people);
app.use(morgan('tiny'));
app.use(express.static('./methods-public'));
// parsing json
app.use(express.json())
app.use('/api/people', api_people);
app.use('/login', _login);
app.listen(8430, () => {
console.log(`server listening to port 8430`);
})
const express = require("express");
const router = express.Router();
module.exports = router;
const express = require("express");
if (!person) {
return res.status(404).json({ success: false, msg: `no entry with id:
${req.params.id}` })
}
let newPeople = people.filter((person) => person.id !== Number(req.params.id))
return res.status(200).json(
{
success: true,
msg: `person with id: ${req.params.id} deleted`,
data: newPeople
})
})
module.exports = router
routes/_api_people.js has route and the function so what we will be doing is to place all the functions in the
controller/people.js and export those functions & import in routes/_api_people.js
Final codes :
./app.js looks the same
const {
getPeople,
postPeople,
putPeople,
deletePeople
} = require("../controller/people");
router.get('/', getPeople)
router.post('/', postPeople)
router.put('/:id', putPeople)
router.delete('/:id', deletePeople)
module.exports = router
const { people } = require('../data');
/**
* GET request on `/api/people`
* @param {Object} req request from api call
* @param {Object} res response to api call
*/
const getPeople = (req, res) => {
res.status(200).json({ success: true, data: people })
}
/**
* POST request on `/api/people`
* @param {Object} req , body contains name object.
* @param {Object} res , response contains Welcome Onject
* @returns
*/
const postPeople = (req, res) => {
console.log("req.body: ", req.body);
const { name } = req.body;
if (!name) {
return res.status(400).json({ success: false, msg: 'No Value provided' })
}
res.status(201).json({ success: true, person: name })
}
/**
* PUT request on `/api/people`
* updates people name with value present in req.body.name for req.body.id
* @param {*} req
* @param {*} res
* @returns
*/
const putPeople = (req, res) => {
const { id } = req.params;
const { name } = req.body;
console.log(id, name);
let person = people.find((person) => person.id === Number(id))
if (!person) {
return res.status(400).json({ success: false, msg: `No entry with id :
${id}` })
}
people.map((person) => {
if (person.id === Number(id)) {
person.name = name;
}
})
res.status(200).json({ success: true, data: people })
}
/**
* DELETE request on `/api/people`
* filters out the person with id provided in req.body
* @param {*} req
* @param {*} res
* @returns
*/
const deletePeople = (req, res) => {
console.log('req.params.id: ', req.params.id);
let person = people.find((person) => person.id === Number(req.params.id))
if (!person) {
return res.status(404).json({ success: false, msg: `no entry with id:
${req.params.id}` })
}
let newPeople = people.filter((person) => person.id !== Number(req.params.id))
return res.status(200).json(
{
success: true,
msg: `person with id: ${req.params.id} deleted`,
data: newPeople
})
}
module.exports = {
getPeople,
postPeople,
putPeople,
deletePeople
}
Flavour 2
const express = require("express");
const {
getPeople,
postPeople,
putPeople,
deletePeople
} = require("../controller/people");
// router.get('/', getPeople)
// router.post('/', postPeople)
// router.put('/:id', putPeople)
// router.delete('/:id', deletePeople)
router.route('/')
.get(getPeople)
.post(postPeople);
router.route('/:id')
.put(putPeople)
.delete(deletePeople);
module.exports = router;