INTRODUCTION TO NODE JS
WHAT IS NODE?
Until recently we could only run JavaScript code in a
web browser only. Node is a JavaScript runtime that
executes the code outside of the browser.
We can use the same JavaScript syntax we know and
love to write server side code, instead of relying on
other languages like java , python , ruby etc.
JavaScript is commonly used to build
1)Web servers
2)Command line tools
3)Native apps( VSCode is a Node app)
4)Video games
5)Drone software
6)A whole lot more
Node V/S client side JavaScript
Because node does not run in a web browser we
don’t have access to all the browser related
stuff. The window, document or Dom or APIS are
not available in Node
Node comes with a bunch of built-in-modules that
don’t exist in the browser , this modules helps
us do things like interacting with the operating
system and
file and folders
PROCESS=> the process object is a global that
provides information about and control over the
current node.js process. As a global it does not need
to be require(‘’) as it is always available to
node.js applications
It can also be explicitly accessed through
require(‘’).
PROCESS.ARGV=> the process.argv property returns an
array containing the CMD arguments passed when the
node.js process was launched. The first element will
be process.execPath. the second element will be the
path to the file being executed. The remaining
arguments will be any additional command like
arguments
console.log("Hello from file.")
console.log(process.argv);
// when we run the file it returns two things 1) the
execution path and second is the path where the file
is stored.
// it returns in an array of elements
// we can also pass arguments while running a
script..
// node args.js biswajeet bisu
// suppose we pass two argument so we need to greet
those two arguments
const args = process.argv.slice(2);
// we are slicing it because the first two elements
in the array are the paths
for (let arg of args) {
console.log(`hello there ${arg}`);
}
file system module
const fs = require('fs');
// here we are creating a reference of the file
system module and storing in a variable. when ever we
need a module we use require to load it to a variable
// suppose I want to create a directory inside which
I will be having other files. we can do that using
the mkdir function
fs.mkdir('Project', { recursive: true }, (err) => {
console.log("folder created successfully!!");
if (err) throw err;
});
// the above function is a asynchronomous function.
// if we are creating synchronomously then a
particular block gets executed first and the ones at
the end have to wait.
fs.mkdirSync('Project');
console.log('the folder has been created');
// now suppose I want to create these folders from
the names which I received as argument
// const foldername = process.argv[2];
// fs.mkdirSync(foldername);
// creating files using JavaScript
// if we want to create files then we can use the
function fs.open(); it takes a flag. in the parameter
we need to provide file path and name , whether we
are creating it for writing or reading . we can also
provide a error function
// suppose I want to create a folder and create 3
files inside it
const foldername = process.argv[2];
fs.mkdirSync(foldername);
fs.open(`${foldername}/index.html`, 'w', (err) => {
if (err) throw err;
console.log("created!!")
})
fs.open(`${foldername}/app.js`, 'w', (err) => {
if (err) throw err;
console.log("created!!")
})
fs.open(`${foldername}/style.css`, 'w', (err) => {
if (err) throw err;
console.log("created!!")
})
// console.log(foldername + "Setup has been
completed!!");
WORKING WITH MODULE AND EXPORTS IN JAVASCRIPT
// sometimes we do require some content of a script
which might be required in other places in that case
we can create our own module just like the file
system(fs);
// creating modules in js means creating functions
inside a js file and exporting it so that it can be
imported in other js files and be used.
// lets create a modules say math and add three
function;
//1-add 2-square 3-greet
const add = (x, y) => {
return x + y;
};
const square = (x) => {
return x * x;
};
const greet = (name) => {
return `hello there ${name}`;
};
const math = {
Add: add,
Square: square,
Greet: greet
}
// now we can directly export these math object using
the keyword module.exports;
module.exports = math;
// now lets create a file test so that we can test
the above module that we created
// we can also export like this
// module.exports.add = add;
we are creating this directory in which we will be
storing the data of few employees and the requiring
it from outside the directory.
just like creating the landing page of a website in
the backend also when ever we are requiring a
directory then its content will be
exported only through the index.js file. everything
is arranged in the index file and then exported as a
whole.
we will be accessing it in the test.js file.
Now we have a directory named EmployeeData
Inside this we have allen.js and paul.js
Allen.js contains the following code
module.exports = {
Name: "Allen",
LastName: "Smithson",
Age: 29,
JobProfile: 'Manager',
Salary: "7.8LPA"
}
Paul.js contains the following code
module.exports = {
Name: "Paul",
LastName: "batemen",
Age: 27,
JobProfile: 'Associate Manager',
Salary: "6.5LPA"
}
The index.js file contains the following code
const Paul = require('./paul');
const Allen = require('./allen');
const paul = require('./paul');
const AllEmployees = [Paul, Allen];
module.exports = AllEmployees;
Introduction to NPM(Node Package Manager)npm is
really two things
A library of thousands of packages published by
other developers that we can use for free
A CMD tool to easily install and manage those
packages in our Node package
Let us see how we can download a package called
give-me-a-joke and use functions that it provides
Adding package globally:- sometimes we
require some packages which are to be used
outside many directory’s . so instead of adding
it for every directory we can simply add it to
the Node Modules where node.js is installed.
The command that we require is
=== > npm install -g <packageName>.
The Package.json
to create a package.json file inside the
command prompt we use the keyword
==> npm init
we are actually creating the package.json file
so that we can keep a record of node modules
which we are using inside a project. we know,
to install a package we use the command
==> npm install <package_name>
here for this project
==> npm install figlet
when the package is added to the directory
then it is also added as dependency in the
package.json
// now after figlet we added colors which is
automatically added to package.json
const figlet = require('figlet');
const colors = require('colors');
figlet("hello world", function (err, data) {
if (err) {
console.log('Something went wrong!!')
console.dir(err);
return;
}
console.log(data);// it will print the
data in ascii code design.
// now lets enhance this and add another
package colors
console.log(data.red);
});
Installing all dependencies for a project.
When we are uploading our projects to any
cloud platforms or github we don’t usually
upload the node modules. This is because a
project might contain more then 5 or 10
dependencies and each consume some memory. So
we just upload everything except the node
modules.
Now if some one wants to download that project
and run it in his/her local system then he /
she can download those dependencies.
We know the package.json contains the details
about all the dependencies which are
added/used in the project. So he/she can
simply download the project and use the
command
== npm install
The node package manager will look for the
packages in the package.json file and install
it automatically in the local system.
Express.js
Express is a fast unopinionated minimalistic
web framework for node js. It helps to build
web pages
It’s just a npm package which comes with a
bunch of methods and optional plugins that we
can use to build web applications and api’s.
Express helps us to
1) Start up a server to listen for
request.
2) Parse incoming request.
3) Match those request to particular
routes .
4) Craft our http response and associated
content.
To install express we use the command
== npm install express
First we need to include the express module in
the index.js
const express = require('express');
then we create a object of the express module
const app = express();
const port = 3000;
the app.listen() function is used to start the server
it takes 2 parameters
1)port number and 2) a callback function
app.listen(port, () => {
console.log('listening at port 3000!'); //
app.listen is used to start a server
})
// app.use(()=>{
// console.log('We got a new request!');
// }) when any incoming request is made then the
app.use invokes itself
// it takes 2 parameters 1) request--> it parses the
incoming request 2) result---> it sends a result
based on that request
// app.use((req, res) => {
// // console.log("we got a request");
// // res.send("here is the object you asked
for!");
// // // we can also send javascript object and
html tag
// // res.send({ name: 'Biswajeet_Mohapatra',
Country: 'India' });
// res.send('<h1>This an h1 tag</h1>');
// })
//Routing ==> it refers to taking incoming request
and a path and matching that with some code.
// suppose I want to add response for 2 different
requests
//1==> cat and 2==>dog
// to do that we use the get methods. it accepts 2
parameter
//1) path or route
//2)a callback Funtion
app.get('/cat', (req, res) => { // if we are
requesting to this url it will render the h1 tag
res.send('<h1>this is a cat page</h1>');
})
app.get('/dog', (req, res) => {
res.send('<h1>this is a dog page</h1>'); //if we
are requesting to this url it will render the h1 tag
})
app.get('/', (req, res) => { // this is the home
route
res.send('<h1>this is the main page</h1>');
})
// these are only get requests. we can also make some
post request
app.post('/cats', (req, res) => {
res.send("<h1>you can upload you cat photos
here</h1>");
})
// if the above request does not match then we can
use the /* path
app.post('/*', (req, res) => {
res.send("<h1>no route available for the current
path</h1>");
})
//now we cannot always check for various routes. so for
that we have to make a pattern matching
// we can do that by using the path
//==> res/:something or r/:something or anything with /:
app.get('/res/:Search', (req, res) => {
// now we can extract the request of the user. the
request object is a json type so we can destructure it
using the keyword params.
const { Search } = req.params;
res.send(`<h1> viewing the contents related to $
{Search} </h1>`);
})
// we can also add multiple string query to the path
using the same :something
app.get('/res/:Search/:PostID', (req, res) => {
const { Search, PostID } = req.params;
res.send(`<h1> viewing the contents related to $
{Search} of POSTID: ${PostID} </h1>`);
})
// working with query strings we can actually access
the query string using the query method on the req
object. it returns a json object
app.get('/Search', (req, res) => {
const { q } = req.query;
if (!q) {
res.send(`<h1>Nothing to show if nothing
searched!!</h1>`);
}
else {
res.send(`<h1>here are the results for ${q}
</h1>`);
}
})
// if the above request does not match then we can use
the /* path
app.post('/*', (req, res) => {
res.send("<h1>no route available for the current
path</h1>");
})
Templating using EJS (Embedded JavaScript)
// templating==> templating allows us to define preset
"pattern" for a webpage, that we can dynamically modify
for example:- we could define a single search template
that displays all the results for a given search term. we
don’t know what the term is or how many results are
present ahead of time. the web page is created on the fly
// we will be doing it using the ejs(embedded JavaScript)
Now let us create another app called secondApp
and use ejs in along with express.js
mkdir secondApp
npm init (to make package.json)
cd secondApp
now we have to install express first
- npm install express
Now we have to download the ejs module
- npm install ejs
Now our program folder is ready!!
Program inside index.js
const express = require('express');
const app = express();
const port = 3000;
app.listen(port, () => {
console.log('Listening at port:3000');
});
// we don’t need to require ejs. express is going to look
for it behind the program. now express assumes that there
is a folder named views where .ejs files are present.
//so we will be creating a views folder
// to use the ejs we need to set it
app.set('view engine', 'ejs');
now inside the views folder we can create a lets say home.ejs file
now inside this home.ejs file we can add the boilerplate of html5
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,
initial-scale=1.0">
<title>Home</title>
</head>
<body>
<h1>Hello from main page</h1>
<!-- now we need to render this home.ejs in the
index.js -->
</body>
</html>
So now inside the index.js we have to render it using the
render method of express.
app.get('/', (req, res) => {
// now we need to render home.ejs here
res.render('home.ejs');
})
The home.ejs file is actually the template.
Passing data to templates
we can directly pass arguments inside this template but
it is not recommended instead we should evaluate our
query in the index.js and send it during rendering as a
json object to home.ejs -->
*) rendering directly inside template
<h2>lucky number is <%= 31 %></h2>
*) sending json object to home.ejs inside the index.js
// suppose I want to generate random number between 1- 10
I can directly pass
// math.florr(math.random()*10)+1%> or we can create it
here save it in a variable and send it as an object
// let us add a route /rand
app.get('/rand', (req, res) => {
const num = Math.floor(Math.random() * 10) + 1;
res.render('home.ejs', { randomNumber: num });
// we can give any name to the key !!
// now we can pass this randomNumber object in the
template
})
When ever we are running the server outside the program
file then the server starts but we cannot the
views/home.ejs because express cannot find the node
modules of ejs outside the localFolder so for that we
need to set the path for the ejs views directory so that
it can be accessed outside the program folder.
In the index.js we have to add the path submodule of the
express module. We have to require it first.
const path = require('path');
app.set('views', path.join(__dirname, '/views'));
// what it does is that we are actually providing the
path where the index.js is present and joining it with
/views folder.
__dirname holds the address where the index file is
located.
// now let us create a route and render the requested
subreddit post in the subreddit.ejs
app.get('/r/:redditPost', (req, res) => {
const { redditPost } = req.params;
res.render('subreddit.ejs', { redditPost });
})
Now lets create a subreddit.ejs file in the views folder.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-
scale=1.0">
<title>
<%= redditPost %>
</title>
</head>
<body>
<h1>Viewing all the post related to <%= redditPost %>
</h1>
</body>
</html>
to render an output inside the .ejs file we use the
syntax
<%= good evening At 9+1 pm =%>
Conditionals in EJS
we can execute the js conditional inside the ejs. for
that we have to write the code inside the
<% %> markup syntax. it actually helps to evaluate an
expression and dosent render it in the dom.
Previously while we were rendering our lucky number we
can add a condition to check whether it is even or odd.
to use conditional in ejs we have to use the syntax
- <% js scripts %>
We have to follow one condition while writing scripts for
ejs
Every js script must be inside the above markup . it
actually helps to evaluate an expression and dosent
render it in the dom
For example
<% if(randomNumber%2===0){ %>
<h2>This is a even number</h2>
<% } else { %>
<h2>This is a odd number</h2>
<% } %>
Looping in EJS
We can use the same symbols as above for writing
looping statements inside a ejs template. For example
<%for(let type of cats){ %>
<p><%= type.name %></p>
<% }%>
/now lets try to create a template for the
subreddit post by requiring data's from a json
file
// first lets add the json file
const redditdata = require('./data.json');
app.get('/r/:redditPost', (req, res) => {
const { redditPost } = req.params;
const data = redditdata[redditPost]; //
here we are matching for the data from the url
if (!data) {
res.send(`<h1>Did not find any data
</h1>`)
}
else {
res.render('subreddit.ejs', { data });
}
})
// serving static Assets in Express
// to serve static files such as images, csss
files and javascript files use the
express.static built-in middleware function in
Express.js
// example
// app.use(express.static('public')); ==> now
we can load the files which are in the public
directory
// now to make it rrun outside the program
folder we need to set it's path
app.use(express.static(path.join(__dirname,
'public')));
// now lets create a style sheet in the public
folder and render it in the subreddit.ejs
// introdution to POST request and handling
POST request
// difference between GET and POST requests
//GET==> used to retrive imformation. Data is
sent via query String. Information is plainly
visible in the URL. Limited ammout of data can
be sent
// Post==> used to post data to the server.
used to write/create/update. Data is sent via
request body, not a query string!!. can send
any sort of data (JSON)
//defining Express Post Routes
// i have created a file named getAndPost.ejs
which has a body. now lets add a route to that
page
app.get('/login', (req, res) => {
res.render('GetAndPost.ejs')
})
// now lets add a post request route
// app.post('/login', (req, res) => {
// res.send("Post request!!")
// })
// we know we can get the requested query
string using the req.params method but incase
of post we have a different approch
// for parsing the post request we need to use
req.body
// req.body==> contains key-value pairs of
data submitted in the request body. By default
it is undefined. and is populated when we use
body parsing middleware such as express.json()
or express.urlencoded().
// to use the express.urlencoded() we have to
pass it inside the app.use
app.use(express.urlencoded({ extended:
true }))
app.post('/login', (req, res) => {
res.send("Data submitted sucessfully!!")
const data = req.body;
console.log(data);
})
// now if we try to send json data instead of
form data we have to use another middleware
known as express.json()
app.use(express.json());
// introduction to Rest Architechture==> the
main idea of REST is treating data on the
server side as a resources that can be CRUDed
(create,read,update,delete).
// the most common way of approching REST is
in formatting of the URLs and HTTP verbs in
your applications
// lets create a resource named as comments on
which we can perform the crud operations
// our REST architechture can be like
// GET /comments -> display all the comments
{Index}
// GET /comments/new -> Form to create a new
comment {New}
// POST /comments -> create a new Comment on
the server {Create}
// GET /comments/:id ->Details for one
specific comment {Show}
// GET /comments/:id/edit form to edit
specific comment {Edit}
// PATCH or PUT/comments/:id -> Update a
comment using id {Update}
// DELETE/DESTROY /comment/:id -> delete a
comment using id {Delete}
const exp = require('constants');
const express = require('express');
const app = express();
// adding the uuid package for getting new
indentifiers
const { v4: uuid } = require('uuid');
const port = 3000;
app.listen(port, () => {
console.log('listening at port
https://localhost/:', port);
})
app.set('view engine ', 'ejs');
// when we are starting the server outside the
program folder then it will be started but the
ejs file will not be rendered because outside
the program folder node modules are not
present. to solve that proble we can use the
path function of the express module
const path = require('path');
app.set('views', path.join(__dirname,
'/views')); // what it does is that we are
actually providing the path where the index.js
is present and joining it with /views folder.
// for parsing the post request we need to use
req.body
// req.body==> contains key-value pairs of
data submitted in the request body. By default
it is undefined. and is populated when we use
body parsing middleware such as express.json()
or express.urlencoded().
// to use the express.urlencoded() we have to
pass it inside the app.use
app.use(express.urlencoded({ extended:
true }));
// to parse the json files we use the
express.json() middleware
app.use(express.json());
// now lets create our resource comments as a
array
const comments = [
{
id: uuid(),
Name: "biswajeet",
tweet: "Hello there! how are you ??"
},
{
id: uuid(),
Name: "Kane",
tweet: "I got my first JOBBBBBBB!!!!
BOOOOOYEAHHHHHHH"
},
{
id: uuid(),
Name: "Ashley",
tweet: "WHOA!! that pretty nice."
},
];
// route to get all comment
app.get('/comments', (req, res) => {
res.render('./comments/index.ejs', {
comments })
})
// route to the form page
app.get('/comments/new', (req, res) => {
res.render('./comments/new.ejs');
})
// // post route for the new comment
// app.post('/comments', (req, res) => {
// const { Name, tweet } = req.body;
// comments.push({ Name, tweet });
// res.send('Your comment has been
added!!')
// })
// when we are getting a post request , after
submiting the data the chrome or any other ask
us wheather we want to resubmit the data that
we enterned while clicking on the back button
of the browser. if we accept it the post
request is sent twice with the same data. Now,
in order to prevent that we use the
redirect('path') method . so that after
sending the post request we get back to our
home/index page
// post route for the new comment also
redirecting user to the comment page
app.post('/comments', (req, res) => {
const { Name, tweet } = req.body;
comments.push({ Name, tweet, id:
uuid() });
res.redirect('/comments');
})
// now we have a problem. we are only adding a
new tweet but we are not giving it a unique id
// now to give each tweet object some unique
id we can use the uuid package
// but we are only going to require the v4
module of it
// const { v4: uuid } = require('uuid');
// now every time we call uuid() we are going
to get a unique identifier
// so lets just upadte the id of the comments
array
// adding a route to get the request from the
user to search for a comment
app.get('/comments/find', (req, res) => {
res.render('./comments/search.ejs');
})
// adding a route to show the comment of a
perticular user
app.post('/comments/search', (req, res) => {
const { id } = req.body;
const comment = comments.find(c => c.id
=== id);
if (!comment) {
res.send(`No data found for ID: $
{id}`);
}
else {
res.render('./comments/show.ejs', {
comment });
}
})
// now lets add a route to update or PATCH a
comment
// route to the form page
app.get('/comments/update', (req, res) => {
res.render('./comments/update.ejs');
})
// route to handle the post request for the
patch
// app.post('/comments/update', (req, res) =>
{
// const { id, tweet } = req.body;
// const comment = comments.find((c) =>
c.id === id);
// if (!comment) {
// res.send(`No data found for ID: $
{id}`);
// }
// else {
// comment.tweet = tweet;
// res.redirect('/comments')
// }
// comment.tweet = tweet;
// })
// now the above route works fine for us but
we are not actually creating a patch route
because patch keyword exist but it is not
available in the html forms
// in the express docs there is a tool present
which we can use and that is called method-
override and we can install it using npm
// after installing we are going to use it's
(override using a query value) method
//==> to use a query string value to override
the method specify the query string as a
string argument to the method-override
function() . to then make the call send a POST
request to a url with the overridden method as
the value of the query string key.
//ex we can do this inside a html form
{/* <form action='/url/:something'
action='/resource?_method=DELETE'>
</form> */}
// we need to require it and also set it as a
middleware
const methodOverride = require('method-
override');
app.use(methodOverride('_method'));
// now we need to add the above part in the
html form
app.patch('/comments/update', (req, res) => {
const { id, tweet } = req.body;
const comment = comments.find((c) => c.id
=== id);
if (!comment) {
res.send(`No data found for ID: $
{id}`);
}
else {
comment.tweet = tweet;
res.redirect('/comments')
}
comment.tweet = tweet;
})
//now similarly we can create a delete request
// adding a route to delete a comment
app.get('/comments/destroy', (req, res) => {
res.render('./comments/delete.ejs')
})
// adding a post route to delete a comment
app.delete('/comments/destroy', (req, res) =>
{
const { id } = req.body;
const comment = comments.find((c) => c.id
=== id);
const index = comments.indexOf(comment);
if (index >= 0) {
comments.splice(index, 1);
res.redirect('/comments');
}
else {
res.send(`could not find tweet for ID:
${id}`);
}
})
Before moving to the below section please
refer to the MONGO db notes.
Express middlewares middleware are just
functions. Each middleware has access to the
request and response objects. Middlewares can
end a http request by sending back a response
by res.send() method.
Or middlewares can be chained together, one
after the another by called method like
next().
Handling error in express
we can send an error if any validation fails
suppose i have a route called auth which
takes query string pwd. if empty , it sends
a error.
app.get('/auth', (req, res) => {
const { pwd } = req.query;
if (pwd === 'halo') {
res.send("you cracked the
password");
}
else {
throw new Error('You have entered a
wrong password');
}
})
writting error handlers=> defining error
handling middleware functions in the same
way as the other middlware functions but
error handling functions have four arguments
rather than three. these are
function(err,req,res,next);
keep in mind that all the error handling
middleware should be at the last of all the
existing middlwares.
app.get('/authenticate', (req, res) => {
const { id } = req.query;
if (id == 1221) {
res.send("You entered a correct
passcode: ")
}
// else {
// // chicken.fly(); // now this will
call the error middleware which prints the
error in the server side.
// }
res.status(401); // here we are sending
a 401 error status that means there is a
unauthoried request made to the server;
res.send('password required!! ');
})
app.use((err, req, res, next) => {
console.log(err); // here we can also
print any other message in the terminal if
error occurs.
})
// defining our own error classes=> for
doing so we are going to create a
AppError.js file and export the class so
that we can use the error class in our index
file by requiring it.
class AppError extends Error {
constructor(message, status) {
super();
this.message = message;
this.status = status
}
}
module.exports = AppError;
// now in the index.js file we have to
require it
const AppError = require(‘./AppError.js’);
app.get('/authenticate', (req, res) => {
const { id } = req.query;
if (id == 1221) {
res.send("You entered a correct
passcode: ")
}
throw new AppError('password required',
401); // we are requiring it and then
throwing it
})
//now lets create a route called admin which
sends a 403 error when made a request and
lets also create a error middleware
app.get('/admin', (req, res) => {
throw new AppError('You are not a admin
', 403);
})
app.use((err, req, res, next) => {
const { status = 401, message =
'unauthorised access' } = err;
res.status(status).send(message);
})
handling async errors=> go to the products
project for the async error notes.
inside an async functions we cannot simply
throw an error. for that we need to use the
next keyword which is to be added to the
function parameter.
app.get('/products/:id', async (req, res,
next) => {
const { id } = req.params;
const foundproduct = await
Product.findById(id);
if (foundproduct) {
res.render('products/show.ejs', {
foundproduct });
}
else {
return next(new AppError('product
not found in the database!!', 404));
}
})
after editing if a user leaves a field black
and submits it will throw an error. to
handle that we can use the try catch and
inside catch we will call the error handling
middlware. this error message will be
printed in the client side. Now it is not
possible to use the try catch block for each
and every route. Instead we can define an
async utility which catches an error and
returns a function.