/Node_Course_130322

Learning Node

Primary LanguageJavaScript

Node_Course_130322

Learning Node

Intro:

Node.js is an open-source, cross-platform, back-end JavaScript runtime environment that allows developers to build server-side applications using JavaScript. In simple terms, it lets you write server-side code using JavaScript, the same language used for front-end development.

One of the biggest advantages of Node.js is its ability to handle a large number of concurrent connections with low overhead. This makes it a popular choice for building real-time, high-traffic applications such as chat applications, online gaming platforms, and social media sites.

Node.js is also known for its event-driven, non-blocking I/O model, which allows it to handle asynchronous operations efficiently. This means that Node.js can handle multiple tasks simultaneously without getting bogged down, making it a good choice for building scalable applications.

Note - nodemon is a tool that helps develop Node.js based applications by automatically restarting the node application when file changes in the directory are detected.
Note - npm run myscriptname
Note- event queues takes in alot of operations at once, node is based on concept of non-blocking async operations but it can still be blocked by a sync blocking operation.

Start:

1.) Run 'npm init' to create a package.json file.

package.json && 'npm install'

The purpose of package.json is to have an Object containing details of all dependencies we installed from NPM as packages, So that the next time we open our code in another computer, we run 'npm install' and that command installs all the dependencies from the package.json into that computer. Everything we install comes from "registery.npmjs.org" For eg: 'npm install uuid' is a package that we can install to generate random ids, Now my package.json file automatically has the details of this dependency like version number;

npm install -g  nodemon          //install nodemon globally
npm install --save-dev nodemon   //add nodemon in dev dependency
npm i dotenv
---------------------
how to use
const dotenv = require('dotenv').config()
const port = process.env.PORT;

**Note-Inside package.json

"scripts": {
    "start":"node index",     //npm run start => because deployment m nodemon nhi chahiye hota
    "dev": "nodemon index"    //npm run dev  => dev m chahiye hota
  }

'npm install -D nodemon'

Nodemon is a tool used in Node.js development that automatically restarts the Node.js application whenever changes are made to the code. This helps developers save time and effort by eliminating the need to manually stop and restart the server every time a code change is made.

Export & import

creating & exporting functions,objects,classes,etc, from other js file

Export

// In a math.js file:
function add(a, b) {
  return a + b;
}

function sub(a, b) {
  return a - b;
}

function mul(a, b) {
  return a * b;
}

function div(a, b) {
  return a / b;
}

module.exports = {
  add: add,
  sub: sub,
  mul: mul,
  div: div,
};
-----------------------
// exports.add = add;
// exports.sub = sub;
// exports.mul = mul;
// exports.div = div;

---------------------------------------------------------------------------------------------------
export function add(a, b) {
  return a + b;
}

export default function multiply(a, b) {
  return a * b;
}

Import

// In another file where you want to use these functions:
const math = require('./math.js');
console.log(math.add(2, 3)); // Output: 5
console.log(math.mul(4, 5)); // Output: 20
---------------------------------------------------
const myFunction = require('./myModule.js').default;

console.log(myFunction(2, 3)); // Output: 6

------------------------------------------------------------------------------------------------------

ES6 WAY

import multiply, { add, subtract } from './math.js';
//multiply is the default export from math.js file; add & subtract is simple export

option2

const person = {
    name: 'John Doe',
    age: 30
}

module.exports = person;
exports.person=person;            //this is also valid

//wrong way
exports = {person:person}  // we need to export to module.exports, creating a new exports file will create a completely new exports object that will not function as expected

or
exporting classes in this manner
class Car {
  constructor(make, model, year) {
    this.make = make;
    this.model = model;
    this.year = year;
  }

  getAge() {
    return new Date().getFullYear() - this.year;
  }
}

module.exports = Car;

importing the above in another js file

const person = require('./person');
console.log(person.name);

or

const Car = require(./car);    //name of the file
const myCar = new Car('Toyota', 'Camry', 2018);
console.log(myCar.name)

Function Wrapper in Node.js files

In Node.js, a function wrapper is a piece of code that surrounds a module's code and provides a layer of abstraction between the module and the rest of the application. It is typically used to wrap the module code inside a function, allowing the module to have its own scope and avoid conflicts with other modules.

Here's an example of a function wrapper in Node.js:

(function(exports, require, module, __filename, __dirname) {
  // Module code goes here
  function greet(name) {
    console.log(`Hello, ${name}!`);
  }

  // Expose the greet function as a module
  module.exports = greet;
});

Core modules can be imoprted as follows

core modules are already included with node so we don't have to install them

path is a module that tells us the file name & directory name

const path = require('path');

File System Module (fs) lets us create files/folders & write, override, join & append data

const fs = require('fs');
const fs = require('fs').promises;  //promises version so we can use .then()

fs.mkdir('test123',(err)=>{       //async module code
if (err) throw err;
console.log( "Folder created" );
});

console.log("test")               //sync
//output => test
            Folder created

# more on this

fs.mkdir('test123')
.then(() => {console.log('folder created')})
.catch((err) => {console.log(err)})

fs.watch('test123/test.txt').then((event, filename) => {console.log(event, filename)})

fs.writeFile('test123/test.txt', 'Hello World').then(() => {console.log('file created')})
.catch((err) => {console.log(err)})

fs.readFile('test123/test.txt', (err,data) => {console.log(data);})

fs.appendFile('test123/test.txt', 'this will append ? ')

try {
const value = fs.readFileSync('test123/tesere.txt', 'utf8')}
catch (err) {
console.log(err)
console.log('code is running')
}
console.log('end of code');

28032023

**os module gives us infor about os**
const os = require('os');

values of os.platform()
// darwin (macOS)
// freebsd (FreeBSD)
// linux (Linux)
// sunos (SunOS)
// win32 (Windows)

if(os.platform() === 'win32'){
console.log("Windows");
}

os.cpus().forEach((cpu, index) => {
console.log(`CPU ${index} : ${cpu.model}`);
})
console.log(os.arch()); //architecture
console.log(os.freemem()); //free memory
console.log(os.networkInterfaces()); //total memory
const EventEmitter = require('events');

class ExamOverEventEmitter extends EventEmitter {}

const examOver = new ExamOverEventEmitter();

examOver.on('examOver', () => {console.log('exam is over says student 1');})

examOver.on('examStarts', () => {console.log('exam is over says student 2');})

examOver.emit('examOver');

examOver.emit('examOver');

**Note - add "type" = "module" in package.json if you want to use ES6 syntax instead of common js (require syntax will be replaced by import)

HTML Module - Create server

  1. The HTTP module in Node.js is one of the core modules and provides functionality to create and operate HTTP servers
  2. The HTTP module can be used to create servers that listen for incoming requests and respond to them with appropriate data.
  3. The HTTP module provides methods to handle incoming requests, such as the request method, URL, headers, and payload.
  4. To create an HTTP server using the HTTP module, you can use the createServer method and pass in a callback function to handle incoming requests.
  5. You can use various methods like statusCode, setHeader, and end to set the response status code, content type, and message.
  6. you can start the server using the listen method.
const http = require('http');

// Create a server that listens for incoming requests
const server = http.createServer((req, res) => {

  // Set the status code of the response
  res.statusCode = 200;

  // Set the content type of the response
  res.setHeader('Content-Type', 'text/plain');

  // Send the response to the client with a message
  res.end('Hello, World!');
});

// Start the server and listen for incoming requests on port 3000
server.listen(3000, () => {
  console.log('Server running at http://localhost:3000/');
});

  1. http.createServer() - This method creates an HTTP server instance. It takes a callback function as an argument that will be called each time a request is made to the server. The callback function takes two arguments: req (the request object) and res (the response object).
  2. res.statusCode - This property sets the HTTP status code of the response. The status code indicates whether a request has been successfully processed or not. The default status code is 200, which means "OK".
  3. res.setHeader() - This method sets a response header. A header is a key-value pair that provides additional information about the response, such as the content type, encoding, or caching instructions.
  4. res.end() - This method signals that the response is complete and sends it to the client. The optional data argument can be used to include a message in the response body.
  5. server.listen() - This method starts the server and begins listening for incoming requests on a specified port. The first argument is the port number to listen on, and the second argument is an optional callback function that will be called once the server has started listening.

RESTful APIs

const http = require('http');

// Create a server
const server = http.createServer((req, res) => {
  // Set the response header
  res.setHeader('Content-Type', 'text/plain');

  // Log the request method, URL, and headers
  console.log(`Received a ${req.method} request for URL: ${req.url}`);
  console.log(`Headers: ${JSON.stringify(req.headers)}`);

  // Handle different request methods and URLs
  if (req.method === 'GET') {
    if (req.url === '/') {
      // Handle root URL
      res.write('Hello, world!');
      res.end();
    } else if (req.url === '/about') {
      // Handle /about URL
      res.write('About us page');
      res.end();
    } else {
      // Handle unknown URLs
      res.statusCode = 404; // Not Found
      res.write('404 - Page not found');
      res.end();
    }
  } else if (req.method === 'POST') {
    // Handle POST request
    let body = '';
    req.on('data', (chunk) => {
      body += chunk;
    });
    req.on('end', () => {
      console.log('Received request body:', body);
      // Process the request body as needed
      res.write('Received request body: ' + body);
      res.end();
    });
  } else {
    // Handle unknown request methods
    res.statusCode = 400; // Bad Request
    res.write('400 - Bad Request');
    res.end();
  }
});

// Start the server and listen for incoming requests
server.listen(3000, () => {
  console.log('Server running at http://localhost:3000/');
});

REST API Concepts & Asynchronous Handling of Data

Concept Description
REST API
  • REST (Representational State Transfer) is an architectural style for designing networked applications.
  • REST APIs use HTTP methods (such as GET, POST, PUT, DELETE) to perform operations on resources over the web.
Asynchronous
  • Asynchronous programming is a pattern where tasks are performed concurrently without blocking the main thread of execution.
  • Allows for efficient handling of multiple requests without waiting for each request to complete before moving on to the next one.
Handling Data
  • REST APIs typically handle data in a serialized format such as JSON or XML.
  • Data is sent in the request body for POST and PUT requests, and received in the request body for PUT and DELETE requests.
  • Data is parsed and processed asynchronously using event listeners or Promise-based APIs.
Event-driven
  • REST APIs in Node.js are often implemented using an event-driven architecture.
  • Event listeners are used to handle incoming requests and perform actions asynchronously.
  • Event-driven programming allows for efficient handling of multiple concurrent requests without blocking the main thread of execution.
Non-blocking I/O
  • Node.js uses a non-blocking I/O model.
  • Allows for handling multiple requests simultaneously without blocking the main thread of execution.
  • Enables building high-performance REST APIs that can handle a large number of concurrent requests efficiently.
Callbacks/Promises
  • Asynchronous programming in Node.js can be done using callbacks, Promises, or async/await.
  • Callbacks are functions that are passed as arguments to asynchronous functions and are invoked when the task is complete.
  • Promises provide a structured way of handling asynchronous operations, allowing for more readable and maintainable code.
  • Async/await is a syntax sugar on top of Promises, making it more concise and expressive for handling asynchronous operations in Node.js.

URL Module

const url =require('url');

const myurl =new URL('https://www.amazon.in/s?k=phone&crid=1GRV2L0V9R8HM&sprefix=phone%2Caps%2C281&ref=nb_sb_noss_1')

console.log(myurl);

//OUTPUT

URL {
  href: 'https://www.amazon.in/s?k=phone&crid=1GRV2L0V9R8HM&sprefix=phone%2Caps%2C281&ref=nb_sb_noss_1',
  origin: 'https://www.amazon.in',
  protocol: 'https:',
  username: '',
  password: '',
  host: 'www.amazon.in',
  hostname: 'www.amazon.in',
  port: '',
  pathname: '/s',
  search: '?k=phone&crid=1GRV2L0V9R8HM&sprefix=phone%2Caps%2C281&ref=nb_sb_noss_1',
  searchParams: URLSearchParams {
    'k' => 'phone',
    'crid' => '1GRV2L0V9R8HM',
    'sprefix' => 'phone,aps,281',
    'ref' => 'nb_sb_noss_1' },
  hash: ''
}

//We now know that we can access all these properties by myurl object

url module methods

// we can format & append to urlobject & get a new url
console.log(url.format(myurl+'99i'));
---------------------------------------------------------------------------------
// we can add/append key:value pair to searchParams
myurl.searchParams.append('user','rahul')

Redirection based on different url => handled from backend

const http = require('http');

const server = http.createServer((req, res) => {
    if(req.url === '/'){
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end('<h1>Home</h1>')
    }
    else if(req.url === '/About'){
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end('<h1>About</h1>')
    }
    else if(req.url === '/Contact'){
        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end('<h1>Contact</h1>')
    }
    else{
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end('Error page on my website in case you enter wrong url')
    }
})

server.listen(5050, ()=>{
    console.log('listening on 5050');
})

Creating an api

// if (req.url === '/api/users') {
  //   const users = [
  //     { name: 'Bob Smith', age: 40 },
  //     { name: 'John Doe', age: 30 }
  //   ];
  //   res.writeHead(200, { 'Content-Type': 'application/json' });
  //   res.end(JSON.stringify(users));
  // }

Dynamic API

// Build file path
  let filePath = path.join(
    __dirname,
    "public",
    req.url === "/" ? "index.html" : req.url
  );

  // Extension of file
  let extname = path.extname(filePath);

  // Initial content type
  let contentType = "text/html";

  // Check ext and set content type
  switch (extname) {
    case ".js":
      contentType = "text/javascript";
      break;
    case ".css":
      contentType = "text/css";
      break;
    case ".json":
      contentType = "application/json";
      break;
    case ".png":
      contentType = "image/png";
      break;
    case ".jpg":
      contentType = "image/jpg";
      break;
  }

  // Check if contentType is text/html but no .html file extension
  if (contentType == "text/html" && extname == "") filePath += ".html";

  // log the filePath
  console.log(filePath);

  // Read File
  fs.readFile(filePath, (err, content) => {
    if (err) {
      if (err.code == "ENOENT") {
        // Page not found
        fs.readFile(
          path.join(__dirname, "public", "404.html"),
          (err, content) => {
            res.writeHead(404, { "Content-Type": "text/html" });
            res.end(content, "utf8");
          }
        );
      } else {
        //  Some server error
        res.writeHead(500);
        res.end(`Server Error: ${err.code}`);
      }
    } else {
      // Success
      res.writeHead(200, { "Content-Type": contentType });
      res.end(content, "utf8");
    }
  });
});

const PORT = process.env.PORT || 5000;

server.listen(PORT, () => console.log(`Server running on port ${PORT}`));