nodejs works on a single thread, non blocking I/O and it handles it in a loop
-
Rest API
-
Microservices
-
Realtime applications
-
CRUD applications (blog/shopping cart)
-
Tools and Utilities (command line tools as an example)
there are core module like:
-
path
-
filesystem (fs)
-
http
to use them, you will call them in a variable (mostly they will be constants)
const path = require('path');
you can also import functions that are exported to other javascript files to use them
const myfile = require('./myfile');
you will start by creating a package.json
file using:
npm init
npm init -y //this won't ask you questions to fill for the package.json file
if you are using a specific project on another device, you can install all of your dependencies by using
npm install
there are also dev dependencies, these dependencies only work on development enviroment not on production
to install a dependency as a dev dependency
npm install -D nodemon
if you want to use elements inside of another file, you can export it
const person = {
name: 'John Doe',
age: 30
}
module.exports = person;
then you can import it in another file
const person = require('./person');
you can also export classes and functions as well
class Person {
constructor(name, age){
this.name = name;
this.age = age;
}
greeting(){
console.log(`My name is ${this.name} and I am ${this.age}`);
}
}
module.exports = Person;
then you can import it and use it
const Person = require('./person');
const person1 = new Person('John Doe', 30);
person1.greeting(); // My name is John Doe and I am 30
keep in mind that nodejs doesn't support ES6 importing
import Person from './person'
you have to use BabelJS or Typescript and see what is backwards compatible to ES5
const path = require('path');
to get the name of the file (base filename)
path.basename(__filename) //path.js
to get the directory name
path.dirname(__filename) // /users/myPc/nodeFile/pathFile
to get the file extension
path.extname(__filename) // .js
to create a path object
path.parse(__filename)
// it will generate this object
{
root: '/',
dir: '/users/myPc/nodeFile/pathFile',
ext: '.js',
name: 'path'
}
since it is an object so you can use any part of it
to concatenate paths
path.join(__dirname, 'test', 'hello.html')
// it will create a path like this:
// /users/myPc/nodeFile/pathFile/test/hello.html
const fs = require('fs');
const path = require('path');
to create a folder
fs.mkdir(path.join(__dirname, '/test'), {}, function(err){
if(err) throw err;
console.log('folder created....');
})
keep in mind that this action is asynchronous so other tasks might happen in the background
there is a synchronous version of this command
to create and write to a file
fs.writeFile(path.join(__dirname, '/test', 'hello.txt'), 'Hello world!', err => {
if (err) throw err;
console.log('File written to.....');
})
you can use arrow functions instead of regular functions
to add to a file (you use it in the callback)
fs.appendFile(path.join(__dirname, '/test','hello.txt'), 'I love Nodejs', err => {
if(err) throw err;
});
to read from file
fs.readFile(path.join(__dirname, '/test', 'hello,txt'), 'utf8', (err, data) => {
if(err) throw err;
console.log(data);
});
// Hello world! I love Nodejs
to rename a file
fs.rename(path.join(__dirname, '/test', 'hello.txt'), path.join(__dirname, '/test', 'helloworld.txt'), err => {
if(err) throw err;
console.log('File renamed......');
});
const os = require('os');
to get the platform
os.platform()
// darwin for macOS and win32 for windows
to get CPU architecture
os.arch()
// x64
to get CPU core info
os.cpu()
// it will return a big object with how many cores and much more
to get free available memory
os.freemem()
// 122388480
to get total memory
os.totalmem()
//34359738368
to get the home directory
os.homedir()
// /users/myPc
to get uptime (time the system has been up)
os.uptime()
// 1305116 (in seconds)
const url = require('url');
to create a url
const myUrl = new url("http://myepicwebsite.com/hello.html/?id=10");
to serialize the url
myUrl.href
myUrl.toString()
// http://myepicwebsite.com/hello.html/?id=10
to get the host
myUrl.host
//myepicwebsite.com
to get the hostname (same as host but minus the port)
myUrl.hostname
//myepicwebsite.com
to get the pathname
myUrl.pathname
// /hello.html
to serialize a query
myUrl.search
// ?id=10
generate a params object (basically queries in an array)
myUrl.searchParams
// { 'id' => '10', 'status' => 'active'}
you can add to that param by appending to it
myUrl.searchParams.append('abc', '123');
// { 'id' => '10', 'status' => 'active', 'abc' => '123'}
you can loop through the params
myUrl.searchParams.forEach((value,name) =>
console.log(`${name}: ${value}`);
);
const EventEmitter = require('events');
first create a class
class MyEmitter extends EventEmitter {}
initialize an object
const theEmitter = new MyEmitter();
create an event listner
theEmitter.on('event', () => console.log('Event!'));
initialize an event
theEmitter.emit('event');
// Event!
const express = require('express');
initialize express
const app = express();
create your endpoint/ route handler
app.get('/', function(req,res){
res.send('Hello world!');
});
listen to a port
app.listen(5000);
basic route handling
app.get('/', function(req,res){
// fetch from database
// load pages
// return JSON
// full access to request and response
})
you can set up a port variable that takes either the server's port or a port of your choice if server doesn't have a port defined to it
const PORT = process.env.PORT || 5000;
app.listen(PORT);
you can parse HTML in a response
app.get('/', (req,res) => {
res.send('<h1> Hello world </h1>');
});
to send a file
const express = require('express');
const path = require('path');
const app = express();
app.get('/', (req,res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
in express, you can set up a static folder to host static content
app.use(express.static(path.join(__dirname,'public')));
to return json
const members = {
// a object that contains users with id/name/email
// id: 1,
// name: 'John Doe',
// email: 'john@doe.com'
}
app.get('/api/members',(req,res) => {
res.json(members);
});
it will stringify the object in json format
creating middleware (code that works behind the scene)
const logger = (req,res,next) => {
console.log(`${req.protocol}://${req.get('host')}${req.originalUrl}`);
next();
}
to use this middleware
app.use(logger);
to use url parameters
app.get('/api/members/:id', (req,res)=> {
res.send(req.params.id);
});
to get a single member from that member's object we created before
app.get('/api/members/:id', (req,res) => {
const found = members.some(member => member.id === parseInt(req.params.id));
if(found){
res.json(member.filter(member => {
member.id === parseInt(req.params.id)
}))
}
else {
res.status(400).json({msg: "member not found"});
}
});
the some function returns a true/false based on the condition if it is satisfied
the filter will return an object with the elements that satisfy its condition
you parse the request parameters to integer because by default it is a string
if not found return an error json with status of 400 (bad request), majority of the requests are send with status 200 (good request) so just to make sure that it is an error you add the 400 status
express routing (you don't have to include every single route in app.js so you can use a router)
assume you created a folder called routes, inside of it a folder called api then a javascript file called member.js
so it will look like this
routes -> api -> members.js
inside members.js
const express = require('express');
const router = express.Router();
const members = {
// that object we define previously
};
router.get('/'(req,res)=> {
res.json(members);
});
module.exports = router;
to use this router, in app.js
app.use('/api/members', require('./routes/api/members'));
if you call now /api/members with a get request, it will give you the members
example if a post request
router.post('/', (req,res) => {
res.send(req.body);
});
the body won't work because it is not parsed
to parse it, you add these lines to app.js
app.use(express.json());
app.use(express.urlencoded({extended: false})); // for url encoding
create a member example:
router.post('/', (req,res) => {
const newMember = {
id: req.body.id, // or you can use a package like uuid
name: req.body.name,
email: req.body.email,
status: 'active'
};
if(!newMember.name || !newMember.email){
return res.status(400).json({msg: "provide email or name"});
}
members.push(newMember);
res.json(members);
});
update a member
router.put('/:id', (req,res) => {
const found = members.some(member => member.id === parseInt(req.params.id));
if(found){
const updateMember = req.body;
members.forEach(member => {
if(member.id === parseInt(req.params.id)){
member.name = updateMember.name ? updateMember.name : member.name;
member.email = updateMember.email ? updateMember.email : member.email;
res.json({msg: "updated"});
}
else {
req.status(400).json({msg: "didn't update, user not found"});
}
})
}
});
delete a member
router.delete('/:id', (req,res) => {
const found = members.some(member => member.id === parseInt(req.params.id));
if(found){
members = members.filter(member => member.id !== parseInt(req.params.id));
res.json({msg: "member deleted"});
}
else {
res.status(400).json({msg: "cannot delete, member not found"});
}
});