globals

Global Objects in Node.js

In Node.js, there are certain objects that are available to you in every module you write. These objects are like the tools in your toolbox, and they can help you do a variety of tasks.

__dirname

__dirname is a global variable that contains the absolute path to the directory of the currently executing script.

Example:

console.log(__dirname); // '/Users/username/project/script.js'

Use Case:

You can use __dirname to access files or perform actions related to the current directory.

__filename

__filename is a global variable that contains the absolute path to the currently executing script file.

Example:

console.log(__filename); // '/Users/username/project/script.js'

Use Case:

You can use __filename to identify the script file that is running.

exports

exports is a global variable that is used to export values from a module. Any properties you assign to exports will be available to other modules that import your module.

Example:

// module1.js
exports.greeting = "Hello world!";

// module2.js
const greeting = require("./module1").greeting;

console.log(greeting); // 'Hello world!'

Use Case:

You can use exports to share data and functionality between modules.

module

The module global variable represents the current module. It contains information about the module, such as its path, exports, and requirements.

Example:

console.log(module.path); // '/Users/username/project/script.js'
console.log(module.exports); // { greeting: 'Hello world!' }
console.log(module.require); // [Function: require]

Use Case:

You can use module to inspect or modify the current module.

require()

require() is a global function that is used to import modules. It takes a module name as an argument and returns the exported object of that module.

Example:

const fs = require("fs");

fs.readFile("README.md", (err, data) => {
  if (err) throw err;
  console.log(data.toString());
});

Use Case:

You can use require() to load and use other modules in your code.


Class: AbortController

Simplified Explanation:

Imagine you have a long-running task that you want to be able to cancel if needed. AbortController is like a traffic cop that can stop the task in progress.

Detailed Explanation:

An AbortController object represents a way to signal that a running operation should be aborted. It has a signal property, which is an AbortSignal object.

An AbortSignal object represents the current state of an asynchronous operation. It has an aborted property, which indicates whether the operation has been aborted.

Code Snippet:

const ac = new AbortController();

// Add an event listener to the signal to listen for the abort event
ac.signal.addEventListener("abort", () => {
  console.log("Aborted!");
});

// Abort the operation
ac.abort();

Real-World Applications:

  • Long-running requests: If you have a long-running HTTP request, you can use an AbortController to cancel it if the user navigates away from the page.

  • Database transactions: You can use an AbortController to cancel a database transaction if the user cancels the operation.

  • WebSockets: You can use an AbortController to close a WebSocket connection when the user closes the browser tab.

Potential Applications:

  • Stop a piece of code that takes a long time to finish

  • If you want to stop loading a page after a certain time

  • Stop a video from playing after a certain time


abortController.abort([reason])

  • reason {any} (Optional) A reason for aborting the signal, which can be retrieved using abortSignal.reason.

Calls the abort method on the abortController, which triggers the abort signal, causing the abortController.signal to emit the 'abort' event. This can be used to cancel an asynchronous operation that is in progress.

Example:

const abortController = new AbortController();

const request = fetch("https://example.com", {
  signal: abortController.signal,
});

// Cancel the request after 5 seconds
setTimeout(() => {
  abortController.abort();
}, 5000);

Applications:

  • Canceling long-running tasks that are not needed anymore.

  • Preventing multiple requests from being sent simultaneously.

  • Gracefully handling network errors by aborting pending requests.


abortController.signal

The signal property of the AbortController interface is an AbortSignal object that indicates if the request has been aborted.

Example:

const controller = new AbortController();
const signal = controller.signal;

fetch("https://example.com", { signal })
  .then((response) => {
    if (signal.aborted) {
      // The request was aborted, so don't process the response.
    } else {
      // The request was successful, so process the response.
    }
  })
  .catch((error) => {
    if (error.name === "AbortError") {
      // The request was aborted, so don't process the error.
    } else {
      // The request failed for some other reason, so process the error.
    }
  });

// Later, if you want to abort the request:
controller.abort();

Real-World Applications:

  • Preventing unnecessary network requests: If a user navigates away from a page before a request has completed, you can use AbortController to prevent the request from completing and wasting resources.

  • Cancelling long-running operations: If you have a long-running operation, such as a database query or a file upload, you can use AbortController to cancel the operation if the user requests it.


AbortSignal

An AbortSignal is a way to signal to other parts of your program that you want to stop what you're doing.

It's like a flag that you can set to tell other parts of your program, "Hey, I'm done here, you can stop too."

One common use for AbortSignal is in a web browser. When you close a tab or window, the browser sends an AbortSignal to all the scripts running in that tab or window. This tells the scripts to stop what they're doing and clean up their resources.

Here's an example of how you might use an AbortSignal in a web browser:

const controller = new AbortController();
const signal = controller.signal;

fetch("/some-url", { signal })
  .then((response) => {
    if (response.ok) {
      // The request was successful
    } else {
      // The request failed
    }
  })
  .catch((error) => {
    // The request failed
  })
  .finally(() => {
    // The request has completed, whether it was successful or not
    controller.abort();
  });

In this example, the AbortSignal is used to tell the fetch() request to stop if the user closes the tab or window. The finally() block is used to clean up the resources used by the request, even if the request was successful.

Another potential application for AbortSignal is in a long-running computation. If you have a computation that is taking a long time, you can use an AbortSignal to allow the user to cancel the computation.

Here's an example of how you might use an AbortSignal in a long-running computation:

const controller = new AbortController();
const signal = controller.signal;

const computation = new Promise((resolve, reject) => {
  // Perform a long-running computation
  setTimeout(() => {
    resolve(result);
  }, 10000);
});

computation
  .then((result) => {
    // The computation was successful
  })
  .catch((error) => {
    // The computation failed
  })
  .finally(() => {
    // The computation has completed, whether it was successful or not
    controller.abort();
  });

In this example, the AbortSignal is used to allow the user to cancel the computation by calling the controller.abort() method. The finally() block is used to clean up the resources used by the computation, even if the computation was successful.


Static method: AbortSignal.abort([reason])

Summary:

This method creates a new AbortSignal that is already in the aborted state.

Parameters:

  • reason (optional): A custom reason for the abort.

Return Value:

A new aborted AbortSignal.

Usage:

You can use the AbortSignal.abort method to create a new AbortSignal that is already in the aborted state. This can be useful in cases where you want to abort an operation immediately without waiting for it to complete.

For example, let's say you have a function that fetches data from a server:

async function fetchData() {
  const response = await fetch("https://example.com/data.json");
  return response.json();
}

You can use the AbortSignal.abort method to abort this fetch operation:

const abortController = new AbortController();
const signal = abortController.signal;

try {
  const data = await fetchData(signal);
  console.log(data);
} catch (error) {
  if (error.name === "AbortError") {
    console.log("The fetch operation was aborted.");
  } else {
    console.error(error);
  }
}

abortController.abort();

In this example, the abortController.abort() call will immediately abort the fetchData operation, and the catch block will handle the AbortError that is thrown.

Potential Applications:

The AbortSignal.abort method can be used in any situation where you want to abort an operation that is in progress. For example, you could use it to:

  • Cancel a long-running operation that is no longer needed.

  • Stop a fetch operation when the user navigates away from a page.

  • Abort a background task that is using too much memory or CPU.


AbortSignal.timeout

Simplified Explanation

The AbortSignal.timeout method creates a new AbortSignal that will automatically abort after a specified number of milliseconds. This can be useful for setting a timeout on an asynchronous operation, such as a fetch request.

In-Depth Explanation

An AbortSignal is an object that can be used to cancel an asynchronous operation. When an AbortSignal is aborted, any operations that are listening to it will be cancelled.

The AbortSignal.timeout method takes a single argument, which is the number of milliseconds to wait before aborting the AbortSignal. After this number of milliseconds has passed, the AbortSignal will be aborted and any operations that are listening to it will be cancelled.

Code Snippet

const abortController = new AbortController();
const abortSignal = abortController.signal;

setTimeout(() => {
  abortController.abort();
}, 1000);

fetch("https://example.com", { signal: abortSignal })
  .then((response) => {
    // Handle the response
  })
  .catch((error) => {
    // Handle the error
  });

In this example, we create an AbortController and an AbortSignal. We then set a timeout to abort the AbortSignal after 1 second. We then use the AbortSignal with a fetch request. If the fetch request takes more than 1 second, it will be cancelled.

Real-World Applications

The AbortSignal.timeout method can be used in a variety of real-world applications, such as:

  • Setting a timeout on a fetch request

  • Setting a timeout on a database query

  • Setting a timeout on a long-running computation

Potential Applications

  • Setting a timeout on a fetch request: This can be useful for preventing a fetch request from hanging indefinitely. For example, you could set a timeout of 10 seconds on a fetch request to the Google Maps API. If the request does not complete within 10 seconds, it will be cancelled.

  • Setting a timeout on a database query: This can be useful for preventing a database query from hanging indefinitely. For example, you could set a timeout of 10 seconds on a query to a large database table. If the query does not complete within 10 seconds, it will be cancelled.

  • Setting a timeout on a long-running computation: This can be useful for preventing a long-running computation from hanging indefinitely. For example, you could set a timeout of 10 minutes on a computation that is processing a large amount of data. If the computation does not complete within 10 minutes, it will be cancelled.


Simplified Explanation of AbortSignal.any(...)

What is AbortSignal?

Imagine you're cooking multiple dishes at once. Each dish has its own timer to prevent it from overcooking. If you want to stop all the timers at the same time, you can create an AbortSignal. It's like a central switch that can stop all the timers when you flip it.

What is AbortSignal.any(...)?

AbortSignal.any(...) takes multiple AbortSignals and combines them into a new AbortSignal, called the composed signal. The composed signal acts like a group controller that monitors all the individual signals.

How does it work?

If any of the individual signals are aborted, the composed signal will also be aborted. This is like turning off the main switch when any of the individual switches are flipped.

Real-world example:

Let's say you're making a web app that loads multiple images simultaneously. Each image has its own load event. You can use AbortSignal.any(...) to create a composed signal that monitors all the load events. If any of the images fail to load, the composed signal will be aborted, and you can display an error message to the user.

Code example:

// Create individual signals for each image load event
const img1LoadSignal = new AbortSignal();
const img2LoadSignal = new AbortSignal();

// Create a composed signal that monitors both individual signals
const anySignal = AbortSignal.any([img1LoadSignal, img2LoadSignal]);

// Add event listeners to handle the composed signal
anySignal.addEventListener("abort", () => {
  // Handle the error scenario
  console.error("One or both images failed to load.");
});

Applications:

  • Coordinating multiple asynchronous operations

  • Handling errors in parallel tasks

  • Managing timeouts in web apps


Abort Event:

What it is:

  • Imagine you're baking a cake and suddenly realize you don't have the right flour. You can "abort" the baking process and start over.

  • The 'abort' event in JavaScript is similar. It allows you to stop an ongoing operation when something goes wrong.

How it works:

  • We use an AbortController to create an AbortSignal.

  • We then use the AbortSignal to start an operation (like a fetch request).

  • If we need to stop the operation for any reason, we can call abortController.abort().

  • This triggers the 'abort' event on the AbortSignal.

Simplified Example:

// Controller to manage the abort request
const abortController = new AbortController();
// Signal to start and abort the operation
const abortSignal = abortController.signal;

fetch("https://example.com", { signal: abortSignal })
  .then((response) => {
    // Success
    console.log("Got the data.");
  })
  .catch((error) => {
    // Something went wrong
    if (error.name === "AbortError") {
      console.log("The operation was aborted.");
    } else {
      console.log("An error occurred.");
    }
  });

// Abort the operation after 5 seconds
setTimeout(() => {
  abortController.abort();
}, 5000);

Real-World Applications:

  • Timeout: If a request takes too long, you can abort it and try again.

  • Manual cancellation: If the user cancels an operation (e.g., closing a dialog box), you can abort it.

  • Error handling: If you encounter an issue during an operation, you can abort it and handle the error.


abortSignal.aborted

  • Type: boolean

  • Value: true after the AbortController has been aborted.

Simplified Explanation:

Imagine you want to create a race between two runners. One runner is abortSignal.aborted and the other is fetch(). abortSignal.aborted starts the race and runs until it's told to stop. fetch() starts the race and runs until it finishes its task. If abortSignal.aborted reaches the finish line first, it raises a flag and fetch() has to stop running. This is useful in situations where you want to be able to stop a long-running task, like fetching data from the internet.

Code Sample:

const controller = new AbortController();
const signal = controller.signal;

fetch("https://example.com", { signal })
  .then((response) => {
    console.log(response);
  })
  .catch((error) => {
    console.error(error);
  });

// Later, if you want to stop the fetch request:
controller.abort();

In this example, the fetch() request will be aborted if the controller.abort() method is called.

Real-World Applications:

  • Cancelling long-running tasks (e.g., fetching data from a server, rendering a large image)

  • Preventing race conditions between multiple asynchronous tasks


abortSignal.onabort is an event that is emitted when the abortController.abort() function is called. This event can be used to handle the abort signal, such as by cleaning up resources or canceling a request.

Here is a simplified example of how to use the abortSignal.onabort event:

const abortController = new AbortController();
const signal = abortController.signal;

signal.addEventListener('abort', () => {
  // Handle the abort signal
  console.log('The request was aborted.');
});

// Later, when you want to abort the request:
abortController.abort();

Potential applications for abortSignal.onabort:

  • Canceling a request: The abortSignal.onabort event can be used to cancel a request, such as an HTTP request or a WebSocket connection.

  • Cleaning up resources: The abortSignal.onabort event can be used to clean up resources, such as closing a database connection or releasing a lock.

Real-world example:

Imagine you are making an HTTP request to a server. You want to be able to cancel the request if the user navigates away from the page before the request completes. You can use the abortSignal.onabort event to handle the abort signal and cancel the request.

Here is an example of how you could implement this:

const abortController = new AbortController();
const signal = abortController.signal;

const request = fetch('https://example.com', {
  signal
});

// Later, when the user navigates away from the page:
abortController.abort();

If the user navigates away from the page before the request completes, the abortSignal.onabort event will be emitted and the request will be canceled.


abortSignal.reason

Simplified Explanation

When you call abort() on an AbortController, you can optionally provide a reason for aborting. This reason is stored in the abortSignal.reason property.

Potential Applications

  • Error handling: If an operation is aborted due to an error, you can use abortSignal.reason to determine the cause of the error.

  • Logging: You can log the abortSignal.reason to help track down the source of an abort.

  • Testing: You can use abortSignal.reason to verify that an operation was aborted for the expected reason.

Example

const controller = new AbortController();
const signal = controller.signal;

// Start an asynchronous operation.
fetch("https://example.com", { signal })
  .then((response) => {
    // The operation completed successfully.
  })
  .catch((error) => {
    // The operation was aborted.
    if (error.name === "AbortError") {
      console.log("The operation was aborted.", error.reason);
    } else {
      console.error("An error occurred.", error);
    }
  });

// Abort the operation after 5 seconds.
setTimeout(() => {
  controller.abort(new Error("Operation timed out"));
}, 5000);

In this example, the AbortController is used to cancel a fetch request after 5 seconds. If the request is aborted, the error.reason property will be set to 'Operation timed out'.


abortSignal.throwIfAborted()

Simplified Explanation:

Imagine you're starting a race and you have a starting gun. If the gun is fired (i.e., abortSignal.aborted is true), it means the race is canceled. This function checks if the starting gun has been fired, and if it has, it throws an error to tell you that the race has been canceled.

In-depth Explanation:

AbortSignal is a way to tell a piece of code (like a function, a loop, or a request) that it needs to stop what it's doing. abortSignal.throwIfAborted() checks if the abortSignal has been fired, and if it has, it throws an error. This error can then be caught by the code that's using the abortSignal to gracefully handle the cancellation.

Code Snippet:

const abortController = new AbortController();
const abortSignal = abortController.signal;

// Start some long-running process using the `abortSignal`
someLongRunningProcess(abortSignal);

// If you want to cancel the process, call `abort()` on the `abortController`
abortController.abort();

Real-World Application:

One potential application of abortSignal.throwIfAborted() is in web applications. Imagine you have a long-running request that you want to cancel if the user navigates away from the page. You can use abortSignal to track whether the user has navigated away, and if they have, you can call abort() on the request to cancel it.

Benefits of Using abortSignal.throwIfAborted():

  • Provides a clean and consistent way to handle cancellation.

  • Makes it easier to write code that gracefully handles cancellation.

  • Helps improve the performance of your application by avoiding unnecessary work.


Class: Blob

A Blob is a collection of bytes. It can be created from a string, a buffer, or an array of bytes. Blobs are immutable, meaning that their contents cannot be changed once they are created.

Creating a Blob

There are several ways to create a Blob:

const blob = new Blob(['Hello', 'world', '!']);

const blob = new Blob(new Buffer('Hello world!'));

const blob = new Blob('Hello world!', {type: 'text/plain'});

The first example creates a Blob from an array of strings. The second example creates a Blob from a Buffer. The third example creates a Blob from a string and specifies the Blob's type as text/plain.

Accessing Blob Data

The data in a Blob can be accessed using the arrayBuffer(), text(), or stream() methods.

blob.arrayBuffer().then(buffer => {
  // Do something with the buffer
});

blob.text().then(text => {
  // Do something with the text
});

blob.stream().pipe(fs.createWriteStream('output.txt'));

The arrayBuffer() method returns a Promise that resolves to an ArrayBuffer containing the Blob's data. The text() method returns a Promise that resolves to a string containing the Blob's data. The stream() method returns a ReadableStream that can be used to read the Blob's data.

Applications of Blobs

Blobs can be used in a variety of applications, including:

  • Storing images and other binary data

  • Sending and receiving files over the network

  • Creating custom data types

Real-World Examples

Here is an example of how to use a Blob to store an image:

const image = new Image();
image.onload = () => {
  const canvas = document.createElement('canvas');
  canvas.width = image.width;
  canvas.height = image.height;
  const ctx = canvas.getContext('2d');
  ctx.drawImage(image, 0, 0);
  const blob = canvas.toBlob();
  // Do something with the blob
};
image.src = 'image.png';

In this example, the Blob is created from the canvas element, which contains the image data. The Blob can then be used to store the image, send it over the network, or create a custom data type.


Class: Buffer

A Buffer is a container for holding binary data. You can access the data in a Buffer using the Buffer.from() method and passing the data you want to store.

Real-World Example

Let's say you want to store the binary data for an image in a Buffer. You can do this using the following code:

// Create a buffer from an image file
const fs = require("fs");
const buffer = Buffer.from(fs.readFileSync("my_image.png"));

// Do something with the buffer
console.log(buffer);

In this example, we are reading the binary data from the my_image.png file and storing it in a Buffer. We can then do whatever we want with the Buffer, such as print it out to the console or send it over a network connection.

Real-World Applications

Buffers are used in a variety of real-world applications, including:

  • Storing binary data in a database

  • Sending binary data over a network connection

  • Processing binary data in a stream

  • Creating and manipulating images and other binary data


Class: ByteLengthQueuingStrategy

Simplified Explanation:

A ByteLengthQueuingStrategy is a rule that tells the browser how to decide when to stop pushing data into a stream. It does this by tracking the amount of data (in bytes) that has been pushed into the stream and comparing it to a specific limit. Once the limit is reached, the strategy tells the browser to stop pushing data.

Details:

  • Purpose: Control the flow of data in a stream based on the amount of bytes pushed.

  • Limit: Defines the maximum number of bytes that can be pushed into the stream before the browser stops.

  • Browser-compatible: Designed to work with browsers that support the Streams API.

Real-World Example:

Imagine you're streaming a video. To ensure a smooth playback experience, the browser needs to regulate how much data is loaded at a time. A ByteLengthQueuingStrategy can be used to set a limit on the number of bytes that can be downloaded before pausing the download. This prevents the browser from overloading and causing buffering issues.

Complete Code Implementation:

const { ByteLengthQueuingStrategy } = require("stream/web");

const strategy = new ByteLengthQueuingStrategy({
  highWaterMark: 1000000, // 1MB
  lowWaterMark: 500000, // 500KB
});

// Create a Readable stream using the strategy
const readableStream = new ReadableStream({
  strategy,
  read() {},
});

Potential Applications:

  • Video streaming: Regulate the flow of data to prevent buffering.

  • File downloads: Limit the number of bytes downloaded at a time to avoid overwhelming the network.

  • Data processing pipelines: Control the amount of data processed at once to ensure efficient usage of resources.


__dirname

Simplified Explanation: __dirname is a special variable in Node.js that represents the directory path of the current script (program) being run.

Detailed Explanation: Node.js has a built-in object called global that contains all globally available variables, including __dirname. Unlike most globally available variables, __dirname is not actually a global variable. Instead, it is a function that returns the directory path where the current script is located.

Real-World Complete Code Implementation and Example:

// Current script file: /home/user/app/main.js

// Print the directory path of the current script
console.log(__dirname); // Output: /home/user/app

Potential Applications in Real World:

  • Accessing File Paths: You can use __dirname to access the paths of other files within the same directory as the current script.

  • Creating Dynamic File Paths: You can use __dirname to dynamically generate file paths based on the location of the current script.

  • Loading Configuration Files: You can use __dirname to load configuration files located in the same directory as the current script.


__filename

  • Simplified Explanation: __filename is a special variable that stores the absolute path to the current JavaScript file being executed. Imagine you have a file called "myScript.js". When you run this file, the __filename variable will contain the full path to "myScript.js" on your computer.

  • Real-World Example:

    console.log(__filename); // Output: /Users/username/my-project/myScript.js
  • Potential Applications:

    • Logging file paths for debugging purposes

    • Creating or reading files based on the current file's location

    • Providing contextual information to external systems


atob(data)

Simplified Explanation

atob() is not a global method but rather a relic from the past.

It is an old and deprecated method used to decode base64-encoded strings. Base64 encoding is a way of representing binary data as a string of characters.

Important: It is no longer recommended to use atob(). Instead, use Buffer.from(data, 'base64') to decode base64-encoded strings.

Real-World Example

Imagine you have a base64-encoded string: "SGVsbG8gd29ybGQh". This represents the binary data "Hello world!".

To decode this string using atob(), you would do the following:

// NOT RECOMMENDED
const decodedString = atob("SGVsbG8gd29ybGQh");
console.log(decodedString); // Prints "Hello world!"

However, it is preferred to use Buffer.from(data, 'base64') instead:

const decodedString = Buffer.from("SGVsbG8gd29ybGQh", "base64").toString();
console.log(decodedString); // Prints "Hello world!"

Potential Applications

  • Decoding base64-encoded data sent over a network (e.g., in a web application)

  • Converting base64-encoded images into binary data for display

  • Encoding and decoding secrets or passwords securely


BroadcastChannel

A BroadcastChannel is a way for multiple tabs or windows to communicate with each other. It's like a chat room, where everyone can listen to and send messages.

How to use it

To create a new BroadcastChannel, you use the new BroadcastChannel() constructor. The channel takes a name, which is used to identify it.

const channel = new BroadcastChannel("my-channel");

Once you have a channel, you can send messages to it using the postMessage() method. The message can be any type of data, such as a string, an object, or a file.

channel.postMessage("Hello, world!");

To listen for messages, you use the addEventListener() method. The event listener takes a function that will be called whenever a message is received.

channel.addEventListener("message", (event) => {
  console.log(event.data);
});

Real-world applications

BroadcastChannel can be used in a variety of applications, such as:

  • Chat rooms: Multiple users can join a chat room and send messages to each other in real time.

  • Multiplayer games: Players in a multiplayer game can use BroadcastChannel to communicate with each other, share game state, and coordinate their actions.

  • Data synchronization: Multiple devices can use BroadcastChannel to share data with each other, such as files, settings, or user preferences.

Example

Here's a simple example of how to use BroadcastChannel to create a chat room:

<!DOCTYPE html>
<html>
  <head>
    <title>BroadcastChannel Chat Room</title>
    <script>
      // Create a new BroadcastChannel
      const channel = new BroadcastChannel("chat-room");

      // Add an event listener to listen for messages
      channel.addEventListener("message", (event) => {
        // Get the message data
        const message = event.data;

        // Log the message to the console
        console.log(message);
      });

      // Send a message to the channel
      channel.postMessage("Hello, world!");
    </script>
  </head>
  <body>
    <h1>Chat Room</h1>
    <input type="text" id="message-input" />
    <button id="send-button">Send</button>
  </body>
</html>

This code creates a new BroadcastChannel with the name chat-room. It then adds an event listener to listen for messages on the channel. When a message is received, it logs the message to the console.

The code also includes a simple chat interface with an input field and a send button. When the user types a message and clicks the send button, it sends the message to the channel.


Simplified Explanation:

btoa(data) is an older function that is no longer recommended for use in Node.js. It was used to convert a string into a Base64 encoded string.

What is Base64?

Base64 is a way of representing data using only the 64 printable ASCII characters. It is used to encode binary data so that it can be sent over networks or stored in text files.

How does btoa work?

btoa takes a string as input and converts it into a Base64 encoded string. For example:

btoa('Hello world!')

This will return the following Base64 encoded string:

SGVsbG8gd29ybGQh

Why is btoa no longer recommended?

btoa has been replaced by a newer function, Buffer.from(data).toString('base64'). This function provides more flexibility and control over the encoding process.

Real-World Example:

One potential application of Base64 encoding is to send binary data over email. Email systems can be limited in the types of characters that they can transmit. By encoding the binary data using Base64, it can be sent over email without any issues.

Improved Code Example:

The following code demonstrates how to use Buffer.from(data).toString('base64') to encode a string into Base64:

const fs = require('fs');

const data = fs.readFileSync('image.png');
const encodedData = Buffer.from(data).toString('base64');

The encodedData variable now contains the Base64 encoded representation of the PNG image.


clearImmediate(immediateObject)

The clearImmediate method is used to cancel an asynchronous operation scheduled using setImmediate. It takes one argument, immediateObject, which is the value returned by setImmediate.

For example:

const immediateObject = setImmediate(() => {
  console.log('This will never be called');
});

clearImmediate(immediateObject);

In this example, the console.log statement will never be called because the immediate operation is canceled using clearImmediate.

Real-world applications

clearImmediate can be used to cancel asynchronous operations that are no longer needed. For example, if you have a function that makes an HTTP request and you decide to cancel the request, you can use clearImmediate to cancel the request.

Another example of using clearImmediate is to prevent a function from being called if a certain condition is met. For example, you could have a function that updates the UI every second. If the user navigates away from the page, you could use clearImmediate to cancel the function so that the UI is not updated unnecessarily.


clearInterval(intervalObject)

clearInterval is a function that cancels a previously created interval. An interval is a timer that repeatedly calls a function at a specified interval.

To use clearInterval, you must first create an interval using the setInterval function. setInterval takes two arguments:

  • The function to be called repeatedly

  • The interval at which to call the function

Once you have created an interval, you can cancel it using clearInterval. clearInterval takes one argument:

  • The interval object returned by setInterval

Here is an example of how to use clearInterval:

// Create an interval that calls console.log() every second
const interval = setInterval(() => {
  console.log("Hello, world!");
}, 1000);

// After 5 seconds, cancel the interval
setTimeout(() => {
  clearInterval(interval);
}, 5000);

Output:

Hello, world!
Hello, world!
Hello, world!
Hello, world!
Hello, world!

Real-world applications

clearInterval can be used in any situation where you need to stop a timer. For example, you could use clearInterval to:

  • Stop a countdown timer

  • Stop a slideshow

  • Stop a video player

  • Stop a game loop

  • Stop a polling loop

Conclusion

clearInterval is a simple but powerful function that can be used to cancel any interval timer. It is a valuable tool for any JavaScript developer.


clearTimeout(timeoutObject)

The clearTimeout() function is used to cancel a previously set timeout.

Syntax

clearTimeout(timeoutObject)

Parameters

timeoutObject: The timeout object returned by the setTimeout() function.

Return Value

None.

Example

const timeout = setTimeout(() => {
  console.log('Hello, world!');
}, 1000);

clearTimeout(timeout);

This example sets a timeout to log 'Hello, world!' to the console after 1 second. However, the clearTimeout() function is called immediately after the timeout is set, so the timeout is canceled and the message is never logged.

Real World Applications

The clearTimeout() function can be used in a variety of real-world applications, such as:

  • Canceling a timeout that is no longer needed.

  • Resetting a timeout to a new value.

  • Preventing a timeout from executing if a certain condition is met.

Potential Applications

  • Canceling a timeout that is no longer needed. For example, if you set a timeout to perform a task, but the task is completed before the timeout expires, you can use clearTimeout() to cancel the timeout.

  • Resetting a timeout to a new value. For example, if you want to extend the amount of time before a timeout expires, you can use clearTimeout() to cancel the original timeout and set a new one with a longer duration.

  • Preventing a timeout from executing if a certain condition is met. For example, if you set a timeout to perform a task, but you want to cancel the timeout if a certain condition is met, you can use clearTimeout() to cancel the timeout when the condition is met.


Class: CompressionStream

What is it?

CompressionStream is a JavaScript class that allows you to compress data as it's being written. This means that you can save space and bandwidth when sending data over the network.

How does it work?

To use CompressionStream, you first need to create a new stream object:

const stream = new CompressionStream("gzip");

You can then use the stream object to write data to it:

stream.write("Hello, world!");

The data that you write to the stream will be compressed before it's sent over the network.

Why would I use it?

You would use CompressionStream to save space and bandwidth when sending data over the network. This can be useful for sending large files or for sending data over a slow connection.

Real-world example

One real-world example of using CompressionStream is to send compressed images over the network. This can help to reduce the amount of time it takes to load images on a website.

// Create a new compression stream
const stream = new CompressionStream("gzip");

// Create a new image element
const image = new Image();

// Set the image's source to the compressed stream
image.src = stream;

// Add the image to the document
document.body.appendChild(image);

Potential applications

CompressionStream can be used in any application where you need to send compressed data over the network. Some potential applications include:

  • Sending large files

  • Sending data over a slow connection

  • Compressing images for websites

  • Compressing data for storage


console Object

The console object is used to print messages to the command line. It has four main methods:

  • console.log() - Prints a message to the standard output (stdout).

  • console.error() - Prints a message to the standard error (stderr).

  • console.warn() - Prints a warning message.

  • console.info() - Prints an informational message.

Example

The following code prints the message "Hello, world!" to the console:

console.log("Hello, world!");

Real-World Applications

The console object is used for debugging and logging information about the execution of a program. For example, you can use console.log() to print the values of variables at different points in a program. You can also use console.error() to print error messages if something goes wrong.

Potential Applications

  • Debugging

  • Logging

  • Diagnostics

  • Monitoring


Class: CountQueuingStrategy

The CountQueuingStrategy class in globals provides a simple flow-control mechanism based on a byte count.

The strategy is implemented as follows:

  1. If the total size of all queued elements is less than or equal to highWaterMark, writers can continue to enqueue data.

  2. If the total size of all queued elements is greater than or equal to highWaterMark, writers are blocked until the queued elements are drained down to below highWaterMark.

The highWaterMark is a configurable property of the CountQueuingStrategy. The default value is 16384.

Real-World Example

The CountQueuingStrategy class can be used in any situation where you need to control the flow of data between a producer and a consumer. For example, you could use it to:

  • Limit the number of bytes that are queued in a stream.

  • Prevent a producer from overwhelming a consumer.

  • Ensure that a consumer has enough time to process data before the producer sends more data.

Complete Code Implementation

The following code shows how to use the CountQueuingStrategy class:

const { CountQueuingStrategy } = require('globals');

const strategy = new CountQueuingStrategy({ highWaterMark: 1024 });

const queue = new TransformStream({
  strategy,
  transform: (chunk, _, callback) => {
    // Process the data in the chunk.
    callback(null, chunk);
  }
});

// Write data to the queue.
queue.write('Hello, world!');

// Read data from the queue.
queue.on('data', (chunk) => {
  // Process the data in the chunk.
});

Potential Applications

The CountQueuingStrategy class has a number of potential applications in real-world scenarios, including:

  • WebSockets: The CountQueuingStrategy class can be used to control the flow of data between a WebSocket server and client. This can help to prevent the server from overwhelming the client with data, and it can also help to ensure that the client has enough time to process data before the server sends more data.

  • Data streams: The CountQueuingStrategy class can be used to control the flow of data in a data stream. This can help to prevent the stream from becoming overwhelmed with data, and it can also help to ensure that downstream consumers have enough time to process data before the stream sends more data.

  • Video and audio streaming: The CountQueuingStrategy class can be used to control the flow of data in a video or audio stream. This can help to prevent the stream from becoming overwhelmed with data, and it can also help to ensure that downstream consumers have enough time to process data before the stream sends more data.


Crypto

Simplified Explanation:

Crypto is a global object in Node.js that provides tools for working with cryptography, such as encrypting and decrypting data.

Detailed Explanation:

  • Stability: Crypto is marked as experimental, meaning it may change in future versions of Node.js.

  • Availability: Crypto is only available if the Node.js binary was specifically compiled with support for the node:crypto module.

  • Purpose: Crypto provides a browser-compatible implementation of the Web Cryptography API, allowing Node.js applications to perform cryptographic operations in a consistent way across different environments.

Real-World Applications:

  • Data Security: Crypto can be used to encrypt sensitive data, such as passwords or financial information, to protect it from unauthorized access.

  • Authentication: Crypto can be used to verify the identity of users or devices by creating and validating digital signatures.

  • Data Integrity: Crypto can be used to ensure that data has not been tampered with by calculating and verifying checksums or hash values.

Code Example:

// Encrypt a message using AES-256 encryption
const crypto = require("crypto");

// Create a random 256-bit encryption key
const key = crypto.randomBytes(32);

// Create an initialization vector (IV) for the encryption
const iv = crypto.randomBytes(16);

// Create a cipher for encryption
const cipher = crypto.createCipheriv("aes-256-cbc", key, iv);

// Encrypt the message
const encryptedMessage = cipher.update("Hello, world!", "utf8");
encryptedMessage += cipher.final();

// Output the encrypted message
console.log(encryptedMessage.toString("hex"));

This example encrypts the message "Hello, world!" using the AES-256 encryption algorithm with a random key and IV. The encrypted message is then printed to the console as a hexadecimal string.


Simplified Explanation of crypto Module in Node.js

The crypto module in Node.js provides a set of functions and classes for performing cryptographic operations, such as encryption, decryption, hashing, and key generation. It allows developers to securely handle sensitive data in their applications.

Topics:

1. Encryption and Decryption

  • Encryption: Converting plaintext (unencrypted data) into ciphertext (encrypted data) that is difficult to decode without the correct key.

  • Decryption: Converting ciphertext back into plaintext using the correct decryption key.

Code Example:

const crypto = require("crypto");

// Encrypt a message
const cipher = crypto.createCipher("aes-256-cbc", "mysecretkey");
const encrypted = cipher.update("Hello World", "utf8", "hex");

// Decrypt the encrypted message
const decipher = crypto.createDecipher("aes-256-cbc", "mysecretkey");
const decrypted = decipher.update(encrypted, "hex", "utf8");

console.log(decrypted); // Output: Hello World

2. Hashing

  • Hashing: Creating a fixed-size, unique representation of data through a mathematical function. Hash values are difficult to reverse, making them useful for secure password storage and data integrity verification.

Code Example:

const crypto = require("crypto");

// Hash a message
const hash = crypto.createHash("sha256");
hash.update("Hello World");
const hashedValue = hash.digest("hex");

console.log(hashedValue); // Output: a36a47356c3c55ad6913759ab96faa130423c6a046cd3c951958111350590e7c

3. Key Generation

  • Key Generation: Creating a random key used for encryption and decryption. Keys can be symmetric (same key for encryption and decryption) or asymmetric (different keys for each operation).

Code Example:

const crypto = require("crypto");

// Generate a symmetric key
const key = crypto.randomBytes(16); // 128-bit key

// Generate an asymmetric key pair
const { publicKey, privateKey } = crypto.generateKeyPairSync("rsa", {
  modulusLength: 2048, // Key size in bits
});

Applications:

  • Secure storage of sensitive data: Encrypting data at rest (e.g., database passwords, user credentials).

  • Data integrity verification: Using hashing to detect any tampering with sensitive data.

  • Authentication and authorization: Generating secure tokens and verifying digital signatures.

  • Encryption and decryption of files: Securing communication and data exchange between devices and services.


CryptoKey

The CryptoKey object represents a cryptographic key. It can be used to encrypt or decrypt data, or to sign or verify signatures.

Properties:

  • type: The type of key. This can be either "public" or "private".

  • algorithm: The algorithm that the key is used with. This can be any of the algorithms supported by the crypto module, such as "AES-256" or "RSA-OAEP".

  • extractable: A boolean value that indicates whether the key can be extracted from the browser. This is typically used for debugging purposes.

Methods:

  • encrypt(data): Encrypts the given data using the key.

  • decrypt(data): Decrypts the given data using the key.

  • sign(data): Signs the given data using the key.

  • verify(data, signature): Verifies the given signature using the key.

Real-world applications:

Cryptographic keys are used in a wide variety of applications, including:

  • Secure communication: Cryptographic keys are used to encrypt and decrypt messages, ensuring that they can only be read by the intended recipients.

  • Digital signatures: Cryptographic keys are used to create digital signatures, which can be used to verify the authenticity of a document or message.

  • Authentication: Cryptographic keys are used to authenticate users, ensuring that they are who they claim to be.

Example:

The following code shows how to use the CryptoKey object to encrypt and decrypt data:

const crypto = require('crypto');

// Generate a new AES-256 key
const key = crypto.createKey('aes-256');

// Encrypt some data
const data = 'Hello, world!';
const encryptedData = crypto.encrypt(data, key);

// Decrypt the data
const decryptedData = crypto.decrypt(encryptedData, key);

// Log the decrypted data
console.log(decryptedData); // Hello, world!

CustomEvent

Simple Explanation:

Imagine you're playing a game where you want to send a message to another player, like "You won!" or "Game over." Instead of using a simple text message, you can use a custom event to send more details, like the winner's name, score, and time played.

Technical Explanation:

A CustomEvent is a special type of event that you can create and send yourself. It's like a regular event, but you can choose the name and include any data you want.

Code Example:

// Create a custom event
const myEvent = new CustomEvent("game-over", {
  detail: {
    winner: "Player 1",
    score: 100,
    time: "2min 30s",
  },
});

// Send the event to an event listener
document.addEventListener("game-over", (event) => {
  console.log(`Game over! Winner: ${event.detail.winner}`);
});

// Dispatch the event
document.dispatchEvent(myEvent);

Real-World Applications:

  • Game development: Send custom events for game over, player wins, item collected, etc.

  • Web applications: Create custom events for login, logout, form submission, etc.

  • Communication between browser components: Send events from one part of the website to another, like parent-child or siblings.


What is DecompressionStream?

Imagine you have a big, compressed file. To use it, you need to "decompress" it, which means expanding it back to its original size. DecompressionStream is a tool that does this decompressing for you. It takes the compressed file and turns it back into a regular, usable file.

How does it work?

DecompressionStream works like a pipe. You give it the compressed data, and it gives you back the uncompressed data. It's like having a magic machine that makes your files bigger!

Real-world example:

You download a large ZIP file. To open the files inside, you can use DecompressionStream to extract them. It will take the compressed ZIP file and create a new folder with all the original files inside.

// Create a DecompressionStream to decompress the ZIP file
const decompressor = new DecompressionStream("deflate");

// Read the compressed ZIP file
const file = await readFile("compressed.zip");

// Pipe the compressed data into the decompressor
decompressor.write(file);

// Wait for the decompression to finish
await decompressor.close();

// The decompressed data is now available in decompressor.readable
const decompressedData = await decompressor.readable.read();

Applications:

DecompressionStream is used in many applications where you need to handle compressed files, such as:

  • Downloading and extracting ZIP files

  • Unpacking tarballs

  • Decoding JPEG or PNG images

  • Extracting audio or video from compressed formats


Event

Definition: An event represents a specific occurrence or change in a system. It encapsulates information about what happened, when it happened, and who or what caused it.

Simplified Explanation: Imagine a button you click on a website. The click on the button is an event that triggers specific actions.

Real-World Application: In a web browser, the click event allows you to interact with buttons, links, and other clickable elements.

Code Example:

// create an event
const clickEvent = new Event("click");

// add an event listener to an element
document.getElementById("myButton").addEventListener("click", (event) => {
  console.log("Button was clicked!");
});

// trigger the event
document.getElementById("myButton").dispatchEvent(clickEvent);

EventTarget

Definition: An EventTarget is an object that can dispatch events, such as buttons, images, or web pages. It provides an interface for adding, removing, and dispatching events.

Simplified Explanation: Think of an EventTarget as a central hub where events from different sources can be managed and distributed.

Real-World Application: EventTargets are essential for handling user interactions in web applications. They enable the browser to track events like clicks, mouse movements, and keystrokes.

Code Example:

// create an EventTarget
const myTarget = new EventTarget();

// add an event listener
myTarget.addEventListener("my-event", (event) => {
  console.log("Received an event!");
});

// dispatch an event
myTarget.dispatchEvent(new Event("my-event"));

EventTarget

An EventTarget is an object that can receive events. It's like a mailbox that can receive letters (events).

Listening for events

To listen for events, you use the addEventListener() method.

const button = document.querySelector("button");

button.addEventListener("click", () => {
  // This function will be called when the button is clicked.
});

The first argument to addEventListener() is the type of event you want to listen for, such as "click", "mousedown", or "keydown".

The second argument is a function that will be called when the event occurs. This function is called an event handler.

Dispatching events

To dispatch an event, you use the dispatchEvent() method.

const button = document.querySelector("button");

button.dispatchEvent(new Event("click"));

This will cause the event handler that was added with addEventListener() to be called.

Real-world applications

EventTargets are used in a wide variety of applications, such as:

  • Creating interactive web pages

  • Handling user input

  • Responding to changes in the DOM

  • Communicating between different parts of a web application

Here is an example of how an EventTarget can be used to create an interactive web page:

<button id="myButton">Click me!</button>

<script>
  const button = document.getElementById("myButton");

  button.addEventListener("click", () => {
    alert("You clicked the button!");
  });
</script>

When the user clicks the button, the event handler will be called and the alert box will be displayed.


Understand Node.js's exports Variable:

What is exports?

Imagine you have a recipe for a delicious cake. When you want to share it with others, you export the recipe so they can make it too. In Node.js, the exports variable is like your recipe book. It holds the functions, objects, or values you want to make available to other files in your program.

How to Use exports:

Just like you add ingredients to a recipe, you add your code to the exports variable using the assignment operator (=) like this:

// Add a function to the exports recipe book
exports.calculateTotal = function (x, y) {
  return x + y;
};

Real-World Implementation:

Suppose you have a file called math.js with the following code:

// math.js
exports.calculateTotal = function (x, y) {
  return x + y;
};

Now, in another file, let's call it app.js, you can import this function from math.js like this:

// app.js
const { calculateTotal } = require("./math");

// Use the imported function
console.log(calculateTotal(10, 20)); // Output: 30

Potential Applications:

exports is essential for modularizing your code and organizing your functions and objects in separate files. It allows you to:

  • Break down your code into manageable and reusable modules.

  • Create custom libraries or modules that can be used in multiple programs.

  • Share code between different parts of your application without cluttering the global scope.

Simplified Example:

Imagine you have a recipe for a cake:

// Recipe book (exports)
exports.addFlour = function(amount) { ... };
exports.addSugar = function(amount) { ... };
exports.mixIngredients = function() { ... };

To share this recipe:

// Other file (requiring)
const { addFlour, addSugar, mixIngredients } = require('./recipe-book');

// Use the recipe
addFlour(2 cups);
addSugar(1 cup);
mixIngredients();

By "exporting" the recipe, you can easily share it with others without having to manually copy and paste each step!


fetch

The fetch function is a browser-compatible implementation of the [fetch()][] function, a modern and easy way to make HTTP requests. It allows you to send requests to remote servers and retrieve responses, such as JSON data, HTML, or images.

Simplified Explanation

Imagine you're a chef in a restaurant. The fetch function is like a special tool that lets you order ingredients from suppliers. You can tell it the URL (address) of the supplier and what you want to order (the HTTP request). The fetch function will then go out and fetch the ingredients (the HTTP response) for you.

Code Snippet

// Make a GET request to fetch data from a server
fetch("https://example.com/data")
  .then((response) => response.json())
  .then((data) => {
    // Use the data returned from the server
    console.log(data);
  })
  .catch((error) => {
    // Handle any errors that occur
    console.error(error);
  });

Real-World Applications

  • Fetching data from APIs: Get information from online services, such as weather, news, or social media feeds.

  • Loading content dynamically: Load HTML, images, or scripts into a webpage after it has loaded, without refreshing the page.

  • Making form submissions: Send form data to a server without refreshing the page.

Potential Applications

  • Interactive web applications: Create dynamic and responsive web pages that update in real time.

  • Real-time data dashboards: Display live data from sensors or feeds.

  • Offline applications: Fetch data and store it locally so that users can access it even without an internet connection.

Improved Code Example

The following code snippet shows how to use fetch to get weather data from an API:

const API_KEY = "YOUR_API_KEY";

// Get the weather forecast for San Francisco
fetch(
  `https://api.openweathermap.org/data/2.5/weather?q=San%20Francisco&appid=${API_KEY}`
)
  .then((response) => response.json())
  .then((data) => {
    // Display the weather forecast
    console.log(
      `The temperature in San Francisco is ${data.main.temp} degrees Celsius.`
    );
  })
  .catch((error) => {
    // Handle any errors
    console.error(error);
  });

File Class

The File class represents a file on the file system. It provides methods to read, write, and manipulate the file's contents.

Initialization:

const fs = require('fs');

const file = new fs.File('myfile.txt');

Methods:

1. file.open()

  • Opens the file for reading, writing, or appending.

  • Takes an optional mode parameter (e.g., 'r' for reading, 'w' for writing, 'a' for appending)

2. file.close()

  • Closes the file, releasing any resources held by the file handler.

3. file.read(buffer, offset, length, position)

  • Reads a specified number of bytes from the file into a buffer.

  • Takes parameters:

    • buffer: The buffer to store the data in.

    • offset: The offset in the buffer to start writing at.

    • length: The number of bytes to read.

    • position: The position in the file to read from (optional).

4. file.write(buffer, offset, length, position)

  • Writes a specified number of bytes from a buffer to the file.

  • Takes parameters:

    • buffer: The buffer to read the data from.

    • offset: The offset in the buffer to start reading from.

    • length: The number of bytes to write.

    • position: The position in the file to write to (optional).

5. file.truncate(len)

  • Truncates the file to a specified length.

  • Takes a parameter:

    • len: The new length of the file.

6. file.stat()

  • Returns information about the file, such as its size, creation date, and permissions.

  • No parameters.

7. file.readlink()

  • Returns the path to the file that a symlink points to.

  • No parameters.

8. file.unlink()

  • Deletes the file.

  • No parameters.

9. file.rename(oldPath, newPath)

  • Renames the file.

  • Takes parameters:

    • oldPath: The original path of the file.

    • newPath: The new path of the file.

Real-World Applications:

  • Creating and editing text files

  • Reading data from configuration files

  • Writing log files

  • Copying and moving files between directories


FormData

The FormData class in Node.js is a way to represent a set of key-value pairs for use in a multipart/form-data HTTP request. It is used to send form data to a server, such as when submitting a form on a web page.

How to create a FormData object

You can create a FormData object by calling the FormData() constructor function. This will create an empty FormData object.

const formData = new FormData();

How to add key-value pairs to a FormData object

You can add key-value pairs to a FormData object using the append() method. The append() method takes two arguments: the key and the value. The key is a string that identifies the data, and the value can be any type of data, such as a string, a number, or a file.

formData.append("username", "admin");
formData.append("password", "secret");
formData.append("profile_picture", file);

How to use a FormData object to send HTTP requests

You can use a FormData object to send HTTP requests by using the fetch() API. The fetch() API is a way to send HTTP requests from JavaScript.

fetch("https://example.com/submit-form", {
  method: "POST",
  body: formData,
  headers: {
    "Content-Type": "multipart/form-data",
  },
})
  .then((response) => {
    // Do something with the response
  })
  .catch((error) => {
    // Do something with the error
  });

Real-world use cases for FormData

FormData is used in a variety of real-world applications, such as:

  • Submitting forms on web pages

  • Uploading files to a server

  • Sending data to a REST API

Potential applications for FormData

Here are some potential applications for FormData:

  • Building a web form that submits data to a server

  • Uploading images to a social media platform

  • Sending data to a machine learning model


global

This is the legacy version of the globalThis property. It refers to the global object, which is the top-level object in the JavaScript environment. In browsers, this is the window object, while in Node.js, it's the global object.

Simplified Explanation:

Imagine the global object as the root of all objects in your JavaScript program. It's like the "master controller" that holds all the variables, functions, and objects that are available to your program.

Real-World Example:

// In a browser, `global` refers to the `window` object
console.log(global === window); // true

// In Node.js, `global` refers to the `global` object
console.log(global === globalThis); // true

// Create a global variable
global.myVariable = "Hello World";

// Access the variable from anywhere in your program
console.log(myVariable); // "Hello World"

Potential Applications:

  • Defining global variables that can be accessed from any module or script in your program.

  • Manipulating the global scope, such as adding or removing properties from the global object.

  • Creating custom global functions that can be used by all parts of your program.

Note:

It's generally recommended to use globalThis instead of global for improved compatibility across different JavaScript environments.


Class: Headers

The Headers class in Node.js is a browser-compatible implementation of the Headers interface, which represents a set of HTTP headers, and provides a convenient way to manage and manipulate them.

Characteristics:

  • Maintains a case-insensitive collection of header names and values.

  • The values associated with each header name are represented as a list of strings.

Usage:

// Create a Headers object from an existing object
const headers = new Headers({
  "Content-Type": "application/json",
  Accept: "application/json",
});

// Add or set a header
headers.set("Authorization", "Bearer 12345");

// Retrieve a header value
console.log(headers.get("Content-Type")); // 'application/json'

// Check if a header exists
console.log(headers.has("Accept")); // true

// Delete a header
headers.delete("Authorization");

// Iterate over all headers
for (const [key, value] of headers.entries()) {
  console.log(`${key}: ${value}`);
}

// Convert to a plain object
const plainObject = Object.fromEntries(headers.entries());

Real-World Applications:

  • Adding custom headers to HTTP requests: When sending out HTTP requests, it's often necessary to specify custom headers, such as authentication credentials, language preferences, or content type. Using the Headers class makes it easy to construct and manage these headers.

// Create a request with custom headers
const requestHeaders = new Headers({
  "Content-Type": "application/json",
  "Accept-Language": "en-US",
});

const request = new Request("https://example.com", {
  method: "POST",
  headers: requestHeaders,
});

fetch(request)
  .then((response) => response.json())
  .then((data) => console.log(data));
  • Interacting with HTTP responses: When receiving HTTP responses, it's often useful to access and process the response headers. The Headers class provides a convenient way to do this.

// Get headers from a response
fetch("https://example.com")
  .then((response) => {
    const headers = response.headers;

    // Read a specific header value
    console.log(headers.get("Content-Type"));

    // Check if a header exists
    console.log(headers.has("Authorization"));
  })
  .catch((error) => console.error(error));

MessageChannel

The MessageChannel class represents a pair of objects that can asynchronously exchange data between pages (a channel). The two objects have port1 and port2 properties, which can be used to send and receive messages, respectively.

Messages are sent using the port1.postMessage() method, which takes a single argument: the data to be sent. The data can be any value, including objects, arrays, and even other MessageChannel objects.

Messages are received using the port2.onmessage event listener. The listener is passed a single argument: an object with a data property containing the data sent by the other port.

MessageChannel objects can be used to communicate between pages in a variety of ways. For example, they can be used to:

  • Send data from a web worker to the main page

  • Send data from a plugin to the main page

  • Communicate between two different browser windows

Here is an example of using MessageChannel objects to send data from a web worker to the main page:

// Create a new MessageChannel object
const channel = new MessageChannel();

// Add an event listener to the second port to receive messages
channel.port2.onmessage = (event) => {
  console.log(event.data); // The data sent from the web worker
};

// Send a message to the first port, which will be received by the web worker
channel.port1.postMessage("Hello from the main page!");

Here is another example of using MessageChannel objects to send data from a plugin to the main page:

// Create a new MessageChannel object
const channel = new MessageChannel();

// Add an event listener to the second port to receive messages
channel.port2.onmessage = (event) => {
  console.log(event.data); // The data sent from the plugin
};

// Send a message to the first port, which will be received by the plugin
channel.port1.postMessage("Hello from the main page!");

Here is an example of using MessageChannel objects to communicate between two different browser windows:

// Create a new MessageChannel object in the first browser window
const channel1 = new MessageChannel();

// Create a new MessageChannel object in the second browser window
const channel2 = new MessageChannel();

// Add an event listener to the second port of the first channel to receive messages
channel1.port2.onmessage = (event) => {
  console.log(event.data); // The data sent from the second browser window
};

// Add an event listener to the second port of the second channel to receive messages
channel2.port2.onmessage = (event) => {
  console.log(event.data); // The data sent from the first browser window
};

// Send a message from the first channel to the second channel
channel1.port1.postMessage("Hello from the first browser window!");

// Send a message from the second channel to the first channel
channel2.port1.postMessage("Hello from the second browser window!");

Certainly! Here's a simplified explanation of the MessageEvent class in Node.js:

Introduction to MessageEvent

Imagine you have two friends, Alice and Bob, who are communicating. Alice sends a message to Bob, and Bob receives it. The MessageEvent class represents the message that Bob receives. It contains information about the message, such as its data, source, and origin.

Properties of MessageEvent

The MessageEvent class has several important properties:

  • data: The actual message that was sent. It can be any type of data, such as a string, number, or object.

  • source: The object that sent the message. In our example, this would be Alice.

  • origin: The origin of the message. This is typically the URL of the website or application that sent the message.

Real-World Example

Let's create a simple Node.js script that uses the MessageEvent class. Imagine you have a server that sends messages to clients. When a client receives a message, it prints it out.

// Server.js
const server = require("http").createServer();

server.on("request", (req, res) => {
  res.writeHead(200, { "Content-Type": "text/plain" });
  res.end("Hello, client!");
});

server.listen(8080);

// Client.js
const WebSocket = require("ws");

const client = new WebSocket("ws://localhost:8080");

client.on("message", (event) => {
  console.log("Message received: ", event.data);
});

client.send("Hello, server!");

Potential Applications

The MessageEvent class has many potential applications in the real world. For example, it can be used for:

  • WebSockets: WebSockets are a technology that allows for real-time communication between a client and a server. The MessageEvent class is used to represent messages that are sent over a WebSocket connection.

  • Electron: Electron is a framework that allows you to build desktop applications using web technologies. The MessageEvent class can be used to communicate between the main process and renderer process in an Electron application.

  • Node.js Inter-Process Communication (IPC): Node.js provides a way for processes to communicate with each other using IPC. The MessageEvent class can be used to represent messages that are sent between processes.


MessagePort

A MessagePort object represents one end of a message channel, allowing messages to be passed between different parts of an application or between different applications within the same origin.

Creating a MessagePort

A MessagePort can be created using the MessageChannel.port1 and MessageChannel.port2 properties, which return two MessagePort objects that are connected to each other.

const { port1, port2 } = new MessageChannel();

Sending Messages

To send a message through a MessagePort, use the postMessage() method. The message can be any serializable value, such as a string, number, array, or object.

port1.postMessage("Hello from port 1!");

Receiving Messages

To receive messages from a MessagePort, add an event listener to the message event. The event handler will receive a MessageEvent object containing the message data.

port2.addEventListener("message", (event) => {
  console.log("Message received:", event.data);
});

Closing a MessagePort

A MessagePort can be closed using the close() method. Once a MessagePort is closed, it can no longer be used to send or receive messages.

port1.close();

Real-World Applications

MessagePort objects are useful for communication between different parts of a web application, such as between the main thread and a web worker. They can also be used for communication between different applications that share the same origin.

Here is an example of a simple chat application that uses MessagePort objects to allow two web pages to communicate with each other:

// Page 1
<script>
  const page1Port = new MessagePort();
  page1Port.addEventListener("message", (event) => {
    console.log("Message received from page 2:", event.data);
  });

  const page2Port = new MessageChannel().port2;
  page2Port.postMessage("Hello from page 1!");
</script>

// Page 2
<script>
  const page2Port = new MessagePort();
  page2Port.addEventListener("message", (event) => {
    console.log("Message received from page 1:", event.data);
  });

  const page1Port = new MessageChannel().port2;
  page1Port.postMessage("Hello from page 2!");
</script>

When the user enters a message in the input field on either page, the message is sent to the other page using the postMessage() method. The message is received on the other page by the message event handler.


module

The module variable represents the current module that is being executed. It contains information about the module, such as its path, exports, and dependencies.

Properties

  • filename: The path to the file that is being executed.

  • exports: An object that contains the exports of the module.

  • id: A unique identifier for the module.

  • loaded: A boolean that indicates whether or not the module has been loaded.

  • parent: The parent module of the current module.

  • paths: An array of paths that are searched for modules.

  • require: A function that is used to load modules.

Methods

  • require(id): Loads a module by its identifier.

  • exports: Exports a value from the module.

Real-World Example

The following code imports the fs module and uses it to read a file:

const fs = require("fs");

fs.readFile("test.txt", "utf8", (err, data) => {
  if (err) {
    console.error(err);
    return;
  }

  console.log(data);
});

Potential Applications

The module variable can be used to:

  • Access information about the current module.

  • Load and export modules.

  • Create custom module loading systems.


Navigator

Imagine you're in your web browser and you want to know some information about the browser itself. That's where the Navigator object comes in. It's like a built-in assistant in your browser that provides various details about its environment.

Topics

1. Finding Out Who You Are:

  • navigator.userAgent: This property tells you the name and version of the browser you're using, such as "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36".

2. Knowing Where You've Been:

  • navigator.history: This property lets you access the history of websites you've recently visited during your current browsing session. You can use it to go back or forward, or to see a list of all the pages you've been to.

3. Figuring Out Where You Are (Location, Location, Location):

  • navigator.geolocation: If you allow your browser to access your location, this property lets you determine where in the world you are. Super helpful if you want to find the closest pizza place or get directions to your favorite park.

4. Handling Languages:

  • navigator.language: This property tells you the language(s) your browser prefers. It's based on the settings in your browser, and it's used to display content in the language you're most comfortable with.

5. Checking Your Capabilities:

  • navigator.plugins: This property shows you a list of plugins that are installed in your browser. Plugins are like extras that extend the functionality of your browser, like Adobe Flash or Java.

Real-World Applications:

  • Website Customization: Websites can use the Navigator object to provide personalized experiences based on your browser and language preferences.

  • Location-Aware Apps: Mobile apps can use geolocation to determine your location and offer relevant services, such as local weather updates or nearby restaurant recommendations.

  • Security: Browsers can use userAgent to detect and prevent malicious websites from exploiting vulnerabilities specific to certain versions or types of browsers.

Example Code:

// Get browser version
console.log(navigator.userAgent);

// Get location (requires user permission)
navigator.geolocation.getCurrentPosition((position) => {
  console.log(`Latitude: ${position.coords.latitude}`);
  console.log(`Longitude: ${position.coords.longitude}`);
});

The navigator object provides information about the browser and its environment. It can be used to access the browser's user agent string, language, and other information.

Properties

  • appCodeName: The name of the browser application.

  • appName: The name of the browser.

  • appVersion: The version of the browser.

  • geolocation: An object that provides access to the browser's geolocation API.

  • language: The language of the browser.

  • languages: An array of languages that the browser supports.

  • onLine: A boolean value that indicates whether the browser is online.

  • platform: The platform that the browser is running on.

  • product: The product name of the browser.

  • productSub: The product sub-name of the browser.

  • userAgent: The user agent string of the browser.

  • vendor: The vendor of the browser.

  • vendorSub: The vendor sub-name of the browser.

Methods

  • javaEnabled(): Returns a boolean value that indicates whether Java is enabled in the browser.

  • taintEnabled(): Returns a boolean value that indicates whether taint tracking is enabled in the browser.

Real-World Examples

The following code snippet shows how to use the navigator object to get the browser's user agent string:

const userAgent = navigator.userAgent;

The following code snippet shows how to use the navigator object to get the browser's language:

const language = navigator.language;

The following code snippet shows how to use the navigator object to check whether the browser is online:

const online = navigator.onLine;

Potential Applications

The navigator object can be used for a variety of purposes, including:

  • Identifying the browser and its environment

  • Customizing the user interface based on the browser's capabilities

  • Detecting changes in the browser's state

  • Tracking the user's location

  • Providing access to the browser's geolocation API


  • {number}

The navigator.hardwareConcurrency property in globals returns the number of logical processors available to the current Node.js instance. This number represents the number of CPUs or cores that can be used to execute tasks in parallel.

Plain English Explanation:

Imagine your computer as a workspace where multiple workers can work at the same time. The hardwareConcurrency property tells you how many workspaces or desks your computer has. The higher the number, the more tasks your computer can handle simultaneously.

Code Snippet:

// Get the number of logical processors
const numCPUs = navigator.hardwareConcurrency;

// Print the result
console.log(`This computer has ${numCPUs} logical processors`);

Real-World Applications:

  • Task parallelization: Applications can distribute tasks across multiple processors to improve performance.

  • Workload balancing: Operating systems can assign processes to different processors to optimize resource utilization.

  • Performance monitoring: Developers can use this property to troubleshoot performance issues and identify potential bottlenecks.


What is navigator.language?

navigator.language is a property in Node.js that tells you the preferred language of the device running the program. This is usually the same as the user's preferred language in their operating system settings.

How does it work?

Node.js uses a library called ICU to determine the preferred language. ICU looks at the default language setting in the operating system and uses that to set the navigator.language property.

What does it look like?

The navigator.language property is a string that represents the language code according to RFC 5646. For example, if the user's preferred language is English in the United States, the navigator.language property will be "en-US".

Example:

// Get the preferred language of the Node.js instance.
const language = navigator.language;

console.log(`The preferred language of the Node.js instance is ${language}.`);

Real-world applications:

  • Translating user interfaces into the user's preferred language.

  • Displaying content in a language that is relevant to the user.

  • Customizing the user experience based on their language preferences.


navigator.languages

  • is an array of strings representing the preferred languages of the Node.js instance.

  • By default navigator.languages contains only the value of navigator.language, which will be determined by the ICU library used by Node.js at runtime based on the default language of the operating system.

  • The fallback value on builds without ICU is ['en-US'].

Real World Complete Code Implementation and Example

// Print the preferred languages
console.log(`The preferred languages are '${navigator.languages}'`);

Potential Applications in Real World

  • Internationalization: The array of preferred languages can be used to customize the application's language settings based on the user's preferences.

  • Localization: The array of preferred languages can be used to determine the appropriate language version of a document or website for the user.

  • Language Detection: The array of preferred languages can be used to detect the language of a user's input, such as a search query or a chat message.


  • {string}

The navigator.platform read-only property returns a string identifying the platform on which the Node.js instance is running.

This property provides information about the underlying operating system and hardware architecture of the environment in which Node.js is running. It is commonly used to determine the specific platform-dependent behavior or optimizations that should be applied within the Node.js application.

For example, a Node.js application that needs to access system-specific resources or perform platform-dependent operations can use the navigator.platform property to tailor its behavior accordingly.

Here is a real-world example that demonstrates how to use navigator.platform:

// Check if the application is running on Windows or macOS
if (navigator.platform === "win32") {
  // Perform Windows-specific operations
  console.log("Running on Windows");
} else if (navigator.platform === "darwin") {
  // Perform macOS-specific operations
  console.log("Running on macOS");
} else {
  // Handle other platforms or provide a generic implementation
  console.log("Running on other platform");
}

In this example, the code checks the navigator.platform property to determine the operating system on which the application is running. This information can be used to perform platform-specific operations or modify the application's behavior accordingly.


navigator.userAgent

Imagine your web browser as a car. The navigator.userAgent property is like the car's sticker that says its make and model. In Node.js, this property tells you about the type of JavaScript runtime you're using, like "Node.js" and its version, like "21".

Real World Example:

When you visit a website, the website might use this property to tailor its content to your browser. For example, if you're using an old browser, the website might show you a simplified version.

Simplified Code Example:

console.log(`The user-agent is ${navigator.userAgent}`); // Prints "Node.js/21"

What is PerformanceEntry?

PerformanceEntry is a class that represents a performance entry in the browser. It provides information about the performance of a specific task, such as the time it took to load a resource.

How do I use PerformanceEntry?

You can get a list of PerformanceEntry objects by using the getEntries() method of the performance object. This method returns an array of PerformanceEntry objects that represent all of the performance entries that have been recorded since the page was loaded.

Each PerformanceEntry object has a number of properties that provide information about the performance of the task. Some of the most common properties include:

  • name: The name of the task.

  • startTime: The time at which the task started.

  • duration: The time it took to complete the task.

  • entryType: The type of task.

Real-world example

The following example shows how to use PerformanceEntry to measure the time it takes to load a resource:

const performance = window.performance;

const entries = performance.getEntries();

for (const entry of entries) {
  if (entry.entryType === "resource") {
    console.log(`${entry.name} took ${entry.duration}ms to load.`);
  }
}

This example will log the name and duration of each resource that was loaded on the page.

Potential applications

PerformanceEntry can be used to:

  • Measure the performance of a website or web application.

  • Identify performance bottlenecks.

  • Optimize the performance of a website or web application.

PerformanceEntry is a powerful tool that can help you improve the performance of your website or web application. By using this tool, you can identify performance bottlenecks and make changes to your code to improve the user experience.

Simplified explanation

Think of PerformanceEntry like a stopwatch that you can use to measure how long it takes for things to happen on a web page. You can use it to measure the time it takes to load a resource, the time it takes to execute a function, or the time it takes for a user to interact with an element on the page.

By using PerformanceEntry, you can identify performance bottlenecks and make changes to your code to improve the user experience. For example, if you notice that a particular resource is taking a long time to load, you can try to optimize the way that you load that resource.

PerformanceEntry is a powerful tool that can help you improve the performance of your website or web application. By using this tool, you can create a better experience for your users.

I hope this helps!


PerformanceMark: Simplified Explanation

What is a PerformanceMark?

Imagine you're running a race. You could use a stopwatch to mark specific points along the way, such as when you start, pass a certain checkpoint, or finish. These marks can help you track your progress and analyze your performance.

In the context of web browsing, PerformanceMark is similar to a stopwatch mark. It allows you to mark specific points in time during the loading and execution of a web page. These marks can help you identify bottlenecks, optimize your code, and improve the user experience.

How to Use PerformanceMark?

To create a PerformanceMark, you call:

performance.mark("someMark");

This will create a mark named "someMark" at the current time. You can then use the performance.getEntries() method to retrieve the mark:

const entries = performance.getEntries();
for (const entry of entries) {
  if (entry.name === "someMark") {
    console.log(entry.startTime);
  }
}

Real-World Example:

Let's say you want to measure how long it takes to load an image on a web page. You could create a PerformanceMark when the image starts loading and another mark when it finishes. The difference between these two marks would tell you the loading time.

// Start the mark when image starts loading
performance.mark("imageStart");

// ... Image loading code ...

// End the mark when image finishes loading
performance.mark("imageEnd");

// Calculate the loading time
const imageLoadTime = performance.getEntriesByName("imageEnd")[0].startTime - performance.getEntriesByName("imageStart")[0].startTime;

Potential Applications:

  • Optimizing website performance: Identify bottlenecks and pinpoint areas for improvement.

  • Debugging: Find and fix issues related to slow loading times or unexpected behavior.

  • Analyzing user experience: Determine how specific actions or features affect page responsiveness and user satisfaction.


PerformanceMeasure

The PerformanceMeasure class in globals is a measure of performance recorded during the execution of a script. It can be used to track things like the time it takes to execute a function, the amount of memory allocated, or the number of times a particular event occurs.

Creating a PerformanceMeasure

You can create a new PerformanceMeasure by calling the performance.measure() method. This method takes two arguments:

  • The name of the measure.

  • A callback function that will be executed when you want to record the measurement.

The following code shows you how to create a new PerformanceMeasure to track the time it takes to execute the myFunction function:

performance.measure("myFunction", () => {
  // Code that you want to measure
  myFunction();
});

Getting the Results of a PerformanceMeasure

Once you have created a PerformanceMeasure, you can get the results by calling the getEntries() method. This method returns an array of PerformanceEntry objects, which contain the following information:

  • The name of the measure.

  • The start time of the measurement.

  • The end time of the measurement.

  • The duration of the measurement.

The following code shows you how to get the results of the myFunction measurement:

const entries = performance.getEntries("myFunction");
console.log(entries[0].duration); // Output: 1000

Using PerformanceMeasure in Real-World Applications

PerformanceMeasures can be used in a variety of real-world applications, such as:

  • Profiling code: You can use PerformanceMeasures to identify bottlenecks in your code and improve its performance.

  • Tracking user interactions: You can use PerformanceMeasures to track how users interact with your website or application and improve the user experience.

  • Debugging performance issues: You can use PerformanceMeasures to debug performance issues and identify the root cause of any problems.

Here is an example of how you can use PerformanceMeasures to profile code:

function myFunction() {
  // Code that you want to profile
}

performance.measure("myFunction", () => {
  myFunction();
});

const entries = performance.getEntries("myFunction");
console.log(entries[0].duration); // Output: 1000

This code will output the time it takes to execute the myFunction function. You can use this information to identify any bottlenecks in the function and improve its performance.


PerformanceObserver

The PerformanceObserver class in Node.js allows you to observe and monitor performance metrics of your application. It provides a way to track performance over time and identify potential bottlenecks or areas for improvement.

Creating a PerformanceObserver

To create a PerformanceObserver, you can use the following syntax:

const observer = new PerformanceObserver((list) => {
  // Do something with the performance entries
});

The constructor takes a callback function as an argument. This callback function will be called whenever new performance entries are observed.

Observing Performance Metrics

Once you have created a PerformanceObserver, you can use the observe() method to start observing specific performance metrics. For example, the following code observes the navigation performance metric:

observer.observe({ entryTypes: ["navigation"] });

You can also observe multiple performance metrics at the same time by passing an array of entry types to the observe() method. For example, the following code observes the navigation, resource, and paint performance metrics:

observer.observe({ entryTypes: ["navigation", "resource", "paint"] });

Callback Function

The callback function that you pass to the PerformanceObserver constructor will be called whenever new performance entries are observed. The callback function takes a single argument, which is a list of PerformanceEntry objects.

Each PerformanceEntry object represents a single performance metric. It contains information about the metric, such as the name of the metric, the start time, the end time, and the duration.

Real-World Use Cases

PerformanceObserver can be used in a variety of real-world applications, such as:

  • Identifying performance bottlenecks in your application

  • Optimizing the performance of your application

  • Tracking the performance of your application over time

  • Debugging performance issues

Example

The following is an example of how to use PerformanceObserver to track the performance of a web page:

const observer = new PerformanceObserver((list) => {
  // Get the navigation performance entry
  const navigationEntry = list.getEntriesByName("navigation")[0];

  // Log the navigation performance entry
  console.log(navigationEntry);
});

// Start observing the navigation performance metric
observer.observe({ entryTypes: ["navigation"] });

This example will log the navigation performance entry to the console. The navigation performance entry contains information about the navigation, such as the start time, the end time, and the duration.


What is PerformanceObserverEntryList?

Imagine you're playing a video game and want to track how fast it loads. You can use PerformanceObserverEntryList to measure how long it takes for certain parts of the game to load, like the levels or graphics.

How to use PerformanceObserverEntryList:

To use PerformanceObserverEntryList, you first need to create a PerformanceObserver object. This object will observe certain performance metrics, like how long it takes for a page to load or how much memory is being used. You can then create an entry list that will store the results of the observation.

Here's an example:

// Create a performance observer
const observer = new PerformanceObserver((entries) => {
  // The entries list contains the performance metrics
  for (const entry of entries) {
    console.log(entry.name, entry.duration);
  }
});

// Start observing
observer.observe({ type: 'longtask' });

// Stop observing after 5 seconds
setTimeout(() => {
  observer.disconnect();
}, 5000);

Real-world Applications:

PerformanceObserverEntryList can be used to:

  • Optimize website performance: Identify bottlenecks and slowdowns in your website's loading process.

  • Troubleshoot performance issues: Diagnose problems that are affecting the performance of your application or website.

  • Track user experience: Monitor how users interact with your website or application and identify areas for improvement.

Example Implementation:

The following code snippet shows how to use PerformanceObserverEntryList to measure the performance of a web page load:

const observer = new PerformanceObserver((entries) => {
  const totalTime = entries[entries.length - 1].startTime - entries[0].startTime;
  console.log(`Page loaded in ${totalTime} ms`);
});

observer.observe({ type: 'navigation' });

PerformanceResourceTiming

The PerformanceResourceTiming class in globals represents the timing information for a resource requested by the document. This includes information such as the time it took to fetch the resource, the time it took to parse the resource, and the time it took to execute the resource.

Properties

The following properties are available on the PerformanceResourceTiming class:

  • connectEnd: The time at which the connection to the server was established.

  • connectStart: The time at which the request was sent to the server.

  • decodedBodySize: The size of the decoded response body in bytes.

  • domainLookupEnd: The time at which the domain lookup for the resource was completed.

  • domainLookupStart: The time at which the domain lookup for the resource was started.

  • duration: The total time it took for the resource to be fetched, parsed, and executed.

  • encodedBodySize: The size of the encoded response body in bytes.

  • entryType: The type of resource timing entry.

  • fetchStart: The time at which the resource was requested.

  • initiatorType: The initiator type of the request.

  • nextHopProtocol: The protocol used for the next hop in the connection.

  • redirectCount: The number of redirects that were followed for the resource.

  • redirectEnd: The time at which the last redirect was completed.

  • redirectStart: The time at which the first redirect was started.

  • requestStart: The time at which the request was started.

  • responseEnd: The time at which the response was received.

  • responseStart: The time at which the first byte of the response was received.

  • secureConnectionStart: The time at which the secure connection was established.

  • startTime: The start time of the request.

  • transferSize: The size of the transferred response body in bytes.

  • workerStart: The time at which the worker was started.

Methods

The following methods are available on the PerformanceResourceTiming class:

  • toJSON(): Returns a JSON representation of the PerformanceResourceTiming object.

Examples

The following code snippet shows how to use the PerformanceResourceTiming class:

const performance = require("performance");

// Get the timing information for all resources requested by the document.
const resources = performance.getEntriesByType("resource");

// Iterate over the resources and log the timing information for each resource.
for (const resource of resources) {
  console.log(resource.name, resource.duration);
}

Potential Applications

The PerformanceResourceTiming class can be used to identify performance bottlenecks and to improve the performance of a web application. For example, you could use the PerformanceResourceTiming class to:

  • Identify resources that are slow to load.

  • Identify resources that are blocking the rendering of the page.

  • Identify resources that are causing errors.

  • Optimize the loading of resources.


What is performance?

performance is a built-in object in Node.js that provides information about the performance of your application. You can use it to measure the time it takes for your code to execute, track memory usage, and identify performance bottlenecks.

How to use performance?

To use performance, you can access it like this:

const performance = require('perf_hooks').performance;

What can you do with performance?

With performance, you can:

  • Measure the time it takes for your code to execute:

    • Use the performance.now() method to get the current time.

    • Subtract the start time from the end time to get the execution time.

  • Track memory usage:

    • Use the performance.memoryUsage() method to get information about the memory usage of your application.

    • This includes the amount of memory used by the heap, the amount of memory used by the executable code, and the amount of memory used by the stack.

  • Identify performance bottlenecks:

    • Use the performance.mark() and performance.measure() methods to create markers and measurements that you can use to identify performance bottlenecks.

    • For example, you can create a marker at the beginning and end of a function to measure how long it takes the function to execute.

Real-world examples of using performance:

Here are some real-world examples of how you can use performance:

  • Measure the performance of your web application:

    • Use performance to track the time it takes for your web application to load and to execute user interactions.

    • This information can help you identify performance bottlenecks and improve the user experience of your application.

  • Track memory usage of your application:

    • Use performance to track the memory usage of your application over time.

    • This information can help you identify memory leaks and optimize the memory usage of your application.

  • Identify performance bottlenecks in your code:

    • Use performance to create markers and measurements that you can use to identify performance bottlenecks in your code.

    • This information can help you improve the performance of your code and make it more efficient.

Potential applications of performance:

performance can be used in a variety of applications, including:

  • Performance optimization:

    • Use performance to identify and optimize performance bottlenecks in your application.

  • Memory leak detection:

    • Use performance to track memory usage over time and identify memory leaks.

  • Code profiling:

    • Use performance to create markers and measurements that you can use to profile your code and identify performance bottlenecks.


What is the process object?

The process object in Node.js represents the current Node.js process. It provides information about the process and allows you to interact with it.

Main Properties and Methods

  • process.pid: Returns the process ID (PID).

  • process.version: Get the current Node.js version.

  • process.exit([code]): Ends the process with an optional exit code.

  • process.platform: The platform the process is running on (e.g., 'linux', 'win32').

  • process.arch: The CPU architecture (e.g., 'x64', 'arm').

Real-World Examples

Get the Process ID:

// Get the PID of the current process
const pid = process.pid;

console.log(`Process ID: ${pid}`);

Exit the Process:

// Exits the process with exit code 0 (success)
process.exit(0);

Check the Platform:

// Check if the process is running on Windows
if (process.platform === "win32") {
  // Do Windows-specific stuff
} else {
  // Do non-Windows-specific stuff
}

Potential Applications

  • Process monitoring: Track process information like CPU usage, memory consumption, and exit codes.

  • Logging: Write logs to specific files or destinations based on the process environment.

  • Error handling: Use the process.exit() method to exit the process gracefully when an unexpected error occurs.

  • Platform-specific code: Adjust behavior based on the operating system the process is running on.


queueMicrotask(callback)

Simplified Explanation

Imagine you're in a race, and you'll run after everyone else has finished their current lap. queueMicrotask is like lining up at the starting line for the next lap.

Detailed Explanation

queueMicrotask() schedules a function to run after the current JavaScript code has finished executing, but before any other JavaScript code that is scheduled to run. It's like a special line in a race where you wait to run only after everyone else has finished their current laps.

Real-World Example

Suppose you have a function called load() that loads some data from a remote server. You might want the data to be available as soon as possible, but you don't want it to delay other JavaScript code that needs to run immediately.

function load() {
  // Fetch data from a remote server. This might take some time.
  fetchData().then((data) => {
    // Data has been loaded. Do something with it.
    console.log("Data loaded:", data);
  });
}

// Queue the `load` function to run after everything else.
queueMicrotask(load);

// Other JavaScript code that needs to run immediately.
console.log("Running immediately");

In this example, the console.log("Running immediately") line will print before the console.log("Data loaded:", data) line, because the load function is scheduled to run after the other JavaScript code.

Potential Applications

  • Asynchronous programming: Perform tasks after other JavaScript code has finished running.

  • Scheduling UI updates: Update the UI after DOM changes have been made.

  • Data fetching: Load data from a remote server without blocking other JavaScript code.


ReadableByteStreamController

Imagine a water pipe that you can read from, but not write to. The ReadableByteStreamController is like a pipe that allows you to read data from a source, one byte at a time.

How it works:

  • You create a new ReadableByteStreamController object.

  • You connect the ReadableByteStreamController to a source of data.

  • The ReadableByteStreamController will start reading data from the source and make it available to you.

  • You can read data from the ReadableByteStreamController using the read() method.

Real-world example:

Imagine you have a file on your computer that you want to read. You can use a ReadableByteStreamController to read the file one byte at a time. Here's how you would do it:

const file = new File(['hello world'], 'hello.txt', {type: 'text/plain'});
const reader = new FileReader();
const controller = new ReadableByteStreamController();

reader.onload = () => {
  controller.enqueue(reader.result);
  controller.close();
};

reader.onerror = () => {
  controller.error(reader.error);
};

reader.readAsArrayBuffer(file);

const data = [];
controller.pipeTo({
  write: (chunk) => data.push(chunk),
  close: () => console.log('File read complete:', Buffer.concat(data).toString())
});

Potential applications:

  • Reading files from disk

  • Streaming data from a network

  • Reading data from a database


Simplified Explanation of ReadableStream in Node.js

What is a ReadableStream?

Imagine you have a hose that's connected to a water source. When you turn on the hose, water flows through it continuously. A ReadableStream is like that hose, but for data. It allows you to read data one chunk at a time, as it becomes available.

How does a ReadableStream work?

A ReadableStream is created by opening a resource that contains data, such as a file or a network connection. Once the stream is created, you can call the read() method on it to get the next chunk of data. If there's no more data available, the read() method will return null.

Example:

// Open a file for reading
const fs = require("fs");
const stream = fs.createReadStream("./myfile.txt");

// Read the file contents one chunk at a time
stream.on("data", (chunk) => {
  console.log(chunk.toString());
});

// When the file has been fully read, log a message
stream.on("end", () => {
  console.log("File has been fully read");
});

Real-World Applications:

  • Reading data from a file or database

  • Processing data from a network connection

  • Streaming video or audio content

Improved Code Snippet:

// Create a ReadableStream from a file
const fs = require("fs");
const stream = fs.createReadStream("./myfile.txt", {
  // Set the chunk size to 10 bytes
  highWaterMark: 10,
});

// Read the file contents one chunk at a time
stream.on("data", (chunk) => {
  console.log(chunk.toString());
});

// When the file has been fully read, log a message
stream.on("end", () => {
  console.log("File has been fully read");
});

Class: ReadableStreamBYOBReader

Stability: 1 - Experimental.

A browser-compatible implementation of [ReadableStreamBYOBReader][].

This web compatible API is available in Node.js without any special flag or polyfills. It is, however, marked experimental as we may not fully support the lifecycle management yet and it may change based on developments in the web platform.

Note: Do not instantiate this class directly. Instead, use [TransformStream.getReader()][].

class ReadableStreamBYOBReader {
  constructor();

  /**
   * Reads a chunk of the specified length from the stream.
   * @param {number} view The buffer to receive read data.
   * @returns {Promise<ReadableStreamBYOBReaderResult>} A promise to the result of the read.
   */
  read(view: ArrayBufferView): Promise<ReadableStreamBYOBReaderResult>;

  /**
   * Releases the given array buffer to the pool of reusable buffers.
   * @param {ArrayBufferView} view The buffer to release.
   */
  release(view: ArrayBufferView): void;

  /**
   * Cancels the stream's chunks used in its back pressure mechanism.
   */
  cancel(): void;
}

The syntax for ReadableStreamBYOBReader constructor in stream for Node.js is:

constructor();

The following code sample shows you how to use the ReadableStreamBYOBReader constructor:

const { ReadableStream } = require("stream/web");

const stream = new ReadableStream({
  start(controller) {
    // Start the stream.

    // Send a bunch of data to start.
    controller.enqueue(Buffer.from("Hello"));
    controller.enqueue(Buffer.from("World!"));

    // Close the stream so the reader can finish.
    controller.close();
  },
});

const reader = stream.getReader();

reader.read(new Uint8Array(10)).then(({ value, done }) => {
  // Do something with the chunk. For example, show a loading bar.
});

Class: ReadableStreamBYOBRequest

Stability: 1 - Experimental.

A browser-compatible implementation of [ReadableStreamBYOBRequest][].

The ReadableStreamBYOBRequest class represents a request to obtain a view (a segment) of a ReadableStream's data. Once created, the request can be moved around the ReadableStream by invoking its read() method and providing a buffer to hold the data. To get the data, read() must be invoked with a ReadableStream and an ArrayBuffer for the data to be copied into. If the requested amount of data (in bytes) is available, read() returns an ArrayBuffer of the requested size containing the data; otherwise, it returns null. To get more data, another read() method must be invoked with the same ArrayBuffer.

To cancel the request, invoke the cancel() method. This method must be invoked before the request completes, otherwise it has no effect. This API is experimental. No browser compatibility is guaranteed and API subject to change.

Real-World Applications

A request object is created whenever a read() method is called on a ReadableStream. One common use case is to use the request object to read data from a network request. For example, the following code uses a fetch() request to fetch a remote file and then uses a ReadableStreamBYOBRequest to read the data from the response:

fetch("https://example.com/data.txt").then((response) => {
  const reader = response.body.getReader();
  const buffer = new ArrayBuffer(1024);
  return reader.read(buffer).then((result) => {
    if (result.done) {
      console.log("Done reading data");
    } else {
      console.log(result.value);
      // Read more data
      return reader.read(buffer).then((result) => {
        if (result.done) {
          console.log("Done reading data");
        } else {
          console.log(result.value);
        }
      });
    }
  });
});

Class: ReadableStreamDefaultController

The ReadableStreamDefaultController class is a built-in implementation of the ReadableStreamController interface for node.js. It provides a default implementation of the methods required by the ReadableStreamController interface, which are used to control the flow of data from a readable stream.

Simplified Explanation

The ReadableStreamDefaultController is like a traffic controller for a stream of data. It manages the flow of data by controlling how much data is allowed to be read at a time. This helps to prevent the stream from becoming overwhelmed and dropping data.

Topics and Explanations

Methods:

  • enqueue(chunk): Adds a chunk of data to the stream.

  • error(e): Signals that an error has occurred.

  • close(): Closes the stream.

Properties:

  • desiredSize: The desired amount of data that the stream should be able to hold before it becomes paused.

  • readable: A flag that indicates whether the stream is currently readable.

  • closed: A flag that indicates whether the stream is closed.

Code Snippet

const {ReadableStreamDefaultController} = require('stream/web');

// Create a new readable stream.
const readableStream = new ReadableStream({
  controller: new ReadableStreamDefaultController(),
});

// Add some data to the stream.
readableStream.controller.enqueue('Hello');
readableStream.controller.enqueue('world');

// Close the stream.
readableStream.controller.close();

Real World Applications

The ReadableStreamDefaultController is used in node.js to manage the flow of data from streams such as files, pipes, and sockets. By controlling the flow of data, the ReadableStreamDefaultController helps to prevent data loss and improve performance.

Potential Applications

  • Reading files from disk: The ReadableStreamDefaultController can be used to control the flow of data when reading files from disk. This can help to prevent the file system from becoming overwhelmed and dropping data.

  • Piping data between streams: The ReadableStreamDefaultController can be used to control the flow of data when piping data between streams. This can help to prevent the downstream stream from becoming overwhelmed and dropping data.

  • Creating custom streams: The ReadableStreamDefaultController can be used to create custom streams that have specific flow control requirements.


ReadableStreamDefaultReader

Simplified Explanation:

Imagine you have a pipe with water flowing through it. The ReadableStreamDefaultReader is like a faucet that lets you control the flow of water:

  • getReader(): Creates a new faucet.

  • read(): Gets a single "chunk" of water (data from the stream).

  • releaseLock(): Stops reading from the stream and allows other faucets to open.

Technical Explanation:

The ReadableStreamDefaultReader is an object that allows you to read data from a ReadableStream. It implements the following methods:

  • constructor(stream): Creates a new reader for the given stream.

  • read(): Reads a single chunk of data from the stream. Returns a promise that resolves to an object with the following properties:

    • value: The chunk of data.

    • done: A boolean indicating whether all chunks have been read.

  • releaseLock(): Releases the lock on the stream, allowing other readers to read data.

Real-World Examples:

  • Reading data from a file:

const fs = require("fs");
const stream = fs.createReadStream("myfile.txt");
const reader = stream.getReader();

reader.read().then((chunk) => {
  console.log(chunk.value.toString());
});
  • Reading data from a network request:

const fetch = require("node-fetch");

fetch("https://example.com")
  .then((res) => res.body.getReader())
  .then((reader) => {
    reader.read().then((chunk) => {
      console.log(chunk.value.toString());
    });
  });

Potential Applications:

  • Asynchronous data processing: Reading data from a stream in chunks can improve performance by avoiding blocking operations.

  • Streaming media: Sending and receiving data over a network in real-time.

  • IO operations: Reading data from files or other sources without having to load the entire data into memory.


require()

What is it?

require() is a function in Node.js that allows you to import modules, which are reusable pieces of code that you can use in your own programs.

How does it work?

When you call require(), you pass it the name of the module you want to import. Node.js will then search for the module and load it into your program.

Real-world example:

Let's say you have a module called my-module.js that contains the following code:

function sayHello() {
  console.log("Hello, world!");
}

exports.sayHello = sayHello;

You can import this module into your program using the following code:

const myModule = require("./my-module.js");

myModule.sayHello(); // Output: Hello, world!

Potential applications:

Modules can be used to organize your code and make it more reusable. For example, you could create a module that contains all of the functions you need to interact with a database. Then, you could import that module into any program that needs to access the database.

Modules can also be used to share code between different programs. For example, you could create a module that contains a library of common utility functions. Then, you could import that module into any program that needs to use those functions.


1. What is a Response?

In a web application, when a user makes a request to a server (e.g., for a webpage, image, or data), the server sends back a response. This response contains the requested content, along with other information such as its status code (e.g., "OK" or "Not Found") and any headers (e.g., "Content-Type" or "Cache-Control").

2. Browser-compatible implementation of Response

The Response class in Node.js is a way to create and manipulate responses that are compatible with how browsers handle them. This means you can use it to send responses to clients in web applications, making it easier to develop and test web applications.

3. Real-world example

Here's an example of using Response to send a simple "Hello, world!" response:

const http = require('http');

const server = http.createServer((request, response) => {
  // Create a new response with the content "Hello, world!"
  const responseBody = 'Hello, world!';
  const response = new Response(responseBody);

  // Send the response to the client
  response.end();
});

// Have the server listen for requests on port 3000
server.listen(3000, () => {
  console.log('Server listening on port 3000');
});

When you visit localhost:3000 in a browser, you will see the message "Hello, world!" displayed.

4. Potential applications

Response can be used in any web application where you need to send custom responses to clients. Some common applications include:

  • Sending JSON data as a response to an API request

  • Redirecting users to a different page

  • Setting cache headers to control how the browser handles the response

  • Streaming large responses to the client in chunks


Request

Stability: 2 - Stable

A browser-compatible implementation of {Request}.

What is a Request?

A Request object represents a request to a web server. It contains information about the request, such as the URL, the HTTP method, and the request headers.

How to use a Request object?

To create a new Request object, you can use the new Request() constructor. The constructor takes a URL and an optional options object as arguments. The options object can contain a variety of properties, such as the HTTP method, the request headers, and the body of the request.

Once you have created a Request object, you can send it to a web server using the fetch() method. The fetch() method takes a Request object as its first argument and returns a Promise object. The Promise object will be resolved with the response from the web server.

Real-world example

The following code shows how to use the Request object to make a GET request to a web server:

const request = new Request('https://example.com');

fetch(request).then((response) => {
  console.log(response.status);
  console.log(response.headers);
  console.log(response.body);
});

Potential applications

The Request object can be used in a variety of applications, such as:

  • Fetching data from a web server

  • Sending data to a web server

  • Making authenticated requests

  • Handling CORS requests


setImmediate(callback[, ...args])

The setImmediate() function is used to execute a callback function asynchronously, after the current operation has completed, but before the next event loop iteration. This means that the callback function will not execute until the current event loop has finished processing all of the current events.

Callback: The callback function is the function that will be executed asynchronously. It can take any number of arguments, which can be passed to the callback function using the ...args parameter.

Example:

The following code snippet shows how to use the setImmediate() function:

setImmediate(function() {
  console.log('This message will be logged after the current event loop iteration.');
});

console.log('This message will be logged immediately.');

In this example, the console.log() statement in the setImmediate() callback function will be logged after the console.log() statement in the main program. This is because the setImmediate() callback function is not executed until the current event loop iteration has finished processing all of the current events.

Applications:

The setImmediate() function can be used to perform tasks that do not need to be executed immediately, but should be executed before the next event loop iteration. For example, the setImmediate() function can be used to:

  • Update the user interface after a long-running task has completed

  • Perform background tasks that do not need to be completed immediately

  • Schedule tasks to be executed at a specific time in the future


setInterval

  • Definition: The setInterval() method in Node.js sets a timer that repeatedly calls a function or executes a code snippet at specified intervals (in milliseconds).

  • Syntax:

setInterval(callback, delay[, ...args]);
  • Parameters:

    • callback: The function to be executed at each interval.

    • delay: The interval (in milliseconds) between each execution of the callback.

    • ...args: Optional arguments to pass to the callback function.

  • Explanation:

setInterval() schedules the execution of a callback function at regular time intervals. It creates an interval timer that runs the callback every 'delay' milliseconds, starting after an initial delay of 'delay' milliseconds.

The callback is typically an anonymous function or an arrow function, and it can take additional arguments (specified after the 'delay' parameter) that will be passed to it at each execution.

When setInterval() is called, it returns a timer object that can be used to clear the interval (stop the repeating execution) at any time using the clearInterval() method.

Real-World Applications:

  • Polls: Checking for new data or updates at regular intervals, such as polling for server status or incoming messages.

  • Animated Effects: Creating smooth animations or visual effects by repeatedly updating elements on the screen.

  • User Interactions: Handling events or user input at specific intervals, such as checking for button clicks or key presses.

  • Background Tasks: Scheduling tasks to run in the background at predefined intervals, such as cleaning up temporary files or sending notifications.

Example:

// Run a callback every 5 seconds
const intervalId = setInterval(() => {
  console.log("Callback executed!");
}, 5000);

// Clear the interval after 10 seconds
setTimeout(() => {
  clearInterval(intervalId);
}, 10000);

Potential Applications:

  • Polling for user activity or input on a web page.

  • Animating a rotating carousel or slider.

  • Sending automatic email notifications at scheduled times.

  • Background cleanup of unused resources to optimize system performance.


setTimeout(callback, delay[, ...args])

The setTimeout() function in Node.js is used to set a timer that will execute a given callback function after a specified delay.

How it works

The syntax of setTimeout() is as follows:

setTimeout(callback, delay[, ...args])

Where:

  • callback is the function that will be executed after the delay. It can take any number of arguments.

  • delay is the number of milliseconds to wait before executing the callback.

  • ...args are any additional arguments that will be passed to the callback function.

Example

Here is an example of how to use setTimeout():

setTimeout(() => {
  console.log("Hello, world!");
}, 1000);

This code will log "Hello, world!" to the console after one second.

Real-world applications

setTimeout() is used in a variety of real-world applications, such as:

  • Creating delays in user interfaces (e.g., fading in an element after one second)

  • Polling for data from a server

  • Scheduling background tasks

Potential applications

Here are some potential applications for setTimeout():

  • Creating a simple countdown timer

  • Displaying a loading animation while data is being fetched

  • Sending a notification after a certain amount of time

  • Scheduling a task to run at a specific time


structuredClone(value[, options])

The structuredClone() method in globals creates a deep copy of the value passed in. This means that a new value is created with the same structure and values as the original value, but it is not linked to or dependent on the original value.

This is in contrast to the clone() method, which creates a shallow copy. A shallow copy is a new value that references the same memory location as the original value. This means that changes to the original value will also be reflected in the shallow copy.

The structuredClone() method is also different from the JSON.parse(JSON.stringify(value)) technique, which is commonly used to create deep copies of values. The JSON.parse(JSON.stringify(value)) technique creates a new value that has the same structure and values as the original value, but it loses any non-JSON-serializable data.

The structuredClone() method is available in Node.js 15.0.0 and later.

Syntax

structuredClone(value[, options])

The following code shows you how to use the structuredClone() method:

const originalValue = {
  foo: 'bar',
  baz: [1, 2, 3]
};

const clonedValue = structuredClone(originalValue);

console.log(clonedValue.foo); // 'bar'
console.log(clonedValue.baz); // [1, 2, 3]

originalValue.foo = 'qux';
originalValue.baz.push(4);

console.log(clonedValue.foo); // 'bar'
console.log(clonedValue.baz); // [1, 2, 3]

Options

The structuredClone() method takes an optional options object. The options object can contain the following properties:

  • transfer: A boolean value that indicates whether or not to transfer the ownership of transferable objects.

  • reviver: A function that is called for each key-value pair in the structured clone. The function can modify the value of the key-value pair.

Potential Applications

The structuredClone() method can be used in a variety of applications, including:

  • Caching: The structuredClone() method can be used to create a deep copy of a value that can be stored in a cache. This ensures that the cached value is not affected by changes to the original value.

  • Data transfer: The structuredClone() method can be used to transfer data between different processes or machines. This ensures that the data is not corrupted during the transfer.

  • Cloning objects with circular references: The structuredClone() method can be used to clone objects that contain circular references. This is not possible with the clone() method or the JSON.parse(JSON.stringify(value)) technique.


SubtleCrypto

What is it?

SubtleCrypto is a JavaScript API that allows you to perform cryptographic operations in the browser. This means you can encrypt and decrypt data, generate and verify digital signatures, and more.

Note: SubtleCrypto is an experimental API and may not be available in all browsers. To check if it is available in your browser, run the following code in the console:

if (typeof SubtleCrypto !== 'undefined') {
  console.log('SubtleCrypto is available!');
} else {
  console.log('SubtleCrypto is not available.');
}

How does it work?

To use SubtleCrypto, you first need to create a new instance of the API. You can do this by calling the crypto.subtle function:

const subtleCrypto = crypto.subtle;

Once you have a SubtleCrypto instance, you can use it to perform a variety of cryptographic operations. For example, to encrypt data, you would use the encrypt function:

const data = 'Hello, world!';

subtleCrypto.encrypt({
  name: 'AES-CBC',
  iv: new Uint8Array(16),
  key: new Uint8Array(32)
}, data)
  .then((result) => {
    console.log('Encrypted data:', result);
  })
  .catch((error) => {
    console.error('Error encrypting data:', error);
  });

Real-world applications

SubtleCrypto can be used in a variety of real-world applications, such as:

  • Secure communication: SubtleCrypto can be used to encrypt and decrypt messages, making them secure from eavesdropping.

  • Digital signatures: SubtleCrypto can be used to create and verify digital signatures, which can be used to prove the authenticity of a message or document.

  • Password storage: SubtleCrypto can be used to securely store passwords, making them difficult to crack.

Potential applications in real world

  • E-commerce: SubtleCrypto can be used to secure online transactions, making them more secure for both customers and businesses.

  • Healthcare: SubtleCrypto can be used to protect patient data, ensuring that it remains confidential.

  • Government: SubtleCrypto can be used to secure government communications and data, making them more secure from attack.


DOMException

The DOMException class represents an error that occurs when using the DOM. It provides additional information about the error, such as the error code and the message.

Properties

  • code: The error code. This is a numeric value that indicates the type of error that occurred.

  • message: The error message. This is a human-readable string that describes the error.

Methods

  • toString(): Returns a string representation of the exception.

Usage

The DOMException class is typically used to handle errors that occur when using the DOM. For example, if you try to access a property on an object that doesn't exist, you will get a DOMException with the error code NotFoundError.

try {
  // Access a property on an object that doesn't exist
  const value = object.nonExistentProperty;
} catch (e) {
  // Handle the error
  if (e instanceof DOMException && e.code === DOMException.NotFoundError) {
    // The property doesn't exist
  }
}

Real-world applications

The DOMException class can be used in a variety of real-world applications, such as:

  • Error handling in web applications

  • Validation of user input

  • Debugging DOM-related issues

Potential applications

  • Error handling in web applications: The DOMException class can be used to handle errors that occur in web applications. For example, if a user tries to submit a form with missing information, you can use a DOMException to display an error message.

  • Validation of user input: The DOMException class can be used to validate user input. For example, if a user enters an invalid email address, you can use a DOMException to display an error message.

  • Debugging DOM-related issues: The DOMException class can be used to debug DOM-related issues. For example, if you are having trouble accessing a particular property on an object, you can use a DOMException to determine if the property exists.


TextDecoder

Simplified Summary:

Imagine your computer has a box of letters. TextDecoder helps you turn those letters into words and sentences in a language you can understand, like English or Spanish.

Detailed Explanation:

TextDecoder is a tool that allows you to convert binary code, which is the language that computers understand, into human-readable text. Binary code is made up of 0s and 1s, but TextDecoder can translate them into letters, numbers, and symbols that we can recognize.

Real-World Example:

Suppose you have a file on your computer that contains a lot of text. The file is stored in binary code, but you want to open it and read the text. TextDecoder can help you do that by converting the binary code into words and sentences that you can understand.

Code Implementation:

Here's a simple code example that uses TextDecoder:

// This is the binary code that represents the text "Hello, world!"
const binaryCode = Buffer.from([72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33]);

// Create a new TextDecoder object
const decoder = new TextDecoder();

// Use the decoder to convert the binary code into text
const text = decoder.decode(binaryCode);

// Print the text to the console
console.log(text); // Output: "Hello, world!"

Potential Applications:

TextDecoder has many potential applications, including:

  • Encoding and decoding text for network communication

  • Reading and writing text files

  • Displaying text on a graphical user interface (GUI)

  • Parsing and processing text data

  • Creating and manipulating character sets


Class: TextDecoderStream

Imagine you have a lot of text that's encoded in a special way, like secret code. To understand it, you need a special tool called a "decoder" that can translate the secret code into normal words you can read.

The TextDecoderStream is like a machine that helps you decode this secret text in a stream of data. It's like having a special conveyor belt that takes in the encoded text and turns it into plain text as it moves along.

How It Works:

  1. You give the TextDecoderStream the encoded text.

  2. The TextDecoderStream has a special power that knows how to decode the secret code.

  3. It decodes the text and sends it out like a stream of water.

  4. You can now read the decoded text as it flows out of the stream.

Real-World Example:

Imagine you're a spy trying to decode secret messages. You have a machine that outputs encoded messages in a stream. You can use the TextDecoderStream to decode these messages as they come in, so you can understand them right away.

Complete Code Implementation:

const decoder = new TextDecoderStream();

// Get the encoded message as a stream
const encodedMessage = getEncodedMessageStream();

// Pipe the encoded message through the decoder
const decodedMessage = encodedMessage.pipeThrough(decoder);

// Listen to the decoded message stream
decodedMessage.addEventListener("data", (event) => {
  // The event.data contains the decoded message
  console.log(event.data);
});

Potential Applications:

  • Decoding secret messages in real-time

  • Translating foreign languages on the fly

  • Converting binary data to text format


TextEncoder

Simplified Explanation:

The TextEncoder class in JavaScript allows you to convert Unicode characters into a sequence of bytes. This is useful for sending text data over the internet or storing it in a format that can be easily interpreted by computers.

Real-World Example:

Let's say you want to send a text message to a friend. Your phone will use a TextEncoder to convert the text into a series of bytes that can be transmitted over the network. When your friend receives the message, their phone will use a TextDecoder to convert the bytes back into text.

Code Implementation:

const encoder = new TextEncoder();
const data = encoder.encode("Hello, world!");

Applications:

  • Sending text data over networks

  • Storing text data in a format that can be easily interpreted by computers

  • Creating hash functions for text data


Simplified Explanation of TextEncoderStream Class

What is TextEncoderStream?

Imagine you have a bunch of text data, like a story or a message. This data is stored in your computer as a series of numbers, called Unicode code points.

TextEncoderStream is like a special machine that takes these numbers and converts them into a different format called UTF-8. UTF-8 is a standard way of representing text on the internet and is used in most browsers.

Using TextEncoderStream

To use TextEncoderStream, you create a new stream and then write the text data to it. The stream will automatically convert the text to UTF-8 as it writes.

Here's an example:

const text = "Hello, world!";
const encoder = new TextEncoderStream();

encoder.write(text);

const encodedData = encoder.read(); // Contains the UTF-8 encoded text

Potential Applications

TextEncoderStream is useful in any situation where you need to convert text data to UTF-8. For example, you could use it to:

  • Send text data to a web browser

  • Encode text data for storage in a database

  • Convert text data to a format that can be read by other applications


Simplified Explanation of TransformStream

What is TransformStream?

TransformStream is a powerful tool in Node.js that allows you to transform data in a stream. It takes input data, processes it in some way, and produces output data. Think of it like a data conveyor belt where you can add or change data as it passes through.

How Does it Work?

TransformStream uses two functions to process data:

  • Transform Function: This function takes the incoming data and transforms it into new data. It can add, modify, or even discard data.

  • Flush Function: This function is called when the input stream is closed. It allows you to flush any remaining data that has not yet been transformed.

Real-World Use Cases

Example 1: Filtering Data

You have a stream of data that contains both important and irrelevant information. You can use TransformStream to filter out the irrelevant information and keep only the data you need.

const stream = new TransformStream({
  transform(chunk, controller) {
    if (chunk.important) {
      controller.enqueue(chunk);
    }
  },
});

stream.pipe(process.stdout); // Output only the important data

Example 2: Encryption

You have a stream of sensitive data that you want to encrypt before sending it over the network. You can use TransformStream to encrypt the data as it passes through the stream.

const stream = new TransformStream({
  transform(chunk, controller) {
    controller.enqueue(encrypt(chunk));
  },
});

stream.pipe(networkSocket); // Send the encrypted data over the network

Example 3: Compression

You want to optimize data transfer by compressing it on the fly. TransformStream can be used to compress data before sending it across the network.

const stream = new TransformStream({
  transform(chunk, controller) {
    controller.enqueue(compress(chunk));
  },
});

stream.pipe(networkSocket); // Send the compressed data over the network

Potential Applications

  • Data Filtering and Cleaning: Remove unwanted or duplicate data from streams.

  • Encryption and Decryption: Protect sensitive data during transmission.

  • Data Compression: Optimize data transfer by reducing its size.

  • Data Validation: Check if data meets certain criteria as it flows through a stream.

  • Data Transformation: Modify or update data in real time, such as changing formats or normalizing values.


Class: TransformStreamDefaultController

The TransformStreamDefaultController class is a browser-compatible implementation of the [TransformStreamDefaultController][] interface. It is used to control the flow of data through a [TransformStream][].

Instance Properties

The following instance properties are available on a TransformStreamDefaultController object:

  • desiredSize: The number of bytes that the controller would like to receive. This property is set by the underlying stream and can be used by the controller to determine how much data to read from the input stream.

  • readable: A boolean value indicating whether the controller is in a readable state. A controller is in a readable state when it is ready to receive data from the input stream.

  • writable: A boolean value indicating whether the controller is in a writable state. A controller is in a writable state when it is ready to receive data from the output stream.

Instance Methods

The following instance methods are available on a TransformStreamDefaultController object:

  • **close(): Closes the controller and the underlying stream.

  • enqueue(chunk): Enqueues a chunk of data to be written to the output stream.

  • error(err): Emits an error event on the underlying stream.

  • **terminate(): Terminates the controller and the underlying stream.

Real-World Applications

The TransformStreamDefaultController class can be used to implement a variety of data processing tasks, such as:

  • Filtering data

  • Transforming data

  • Chunking data

Example

The following example shows how to use a TransformStreamDefaultController to implement a simple filter stream:

const { TransformStream } = require('stream/web');

const filterStream = new TransformStream({
  transform(chunk, controller) {
    // Filter the data
    if (chunk.toString() !== 'filtered') {
      controller.enqueue(chunk);
    }
  }
});

const readableStream = /* ... */;
const writableStream = /* ... */;

readableStream.pipeThrough(filterStream).pipeTo(writableStream);

This stream will only pass data that is equal to the string filtered to the output stream.


URL

The URL class in Node.js represents an immutable URL object. It provides an easy way to parse and manipulate URLs, ensuring that they are always in a valid format.

Constructor

new URL(url, base)
  • url: The URL string or object to parse.

  • base: An optional URL object or string to use as the base URL for relative URLs.

Example

const url = new URL('https://example.com');
console.log(url.hostname); // 'example.com'

Properties

The URL class has several properties that provide information about the URL:

  • href: The complete URL string.

  • protocol: The protocol of the URL (e.g. 'https').

  • hostname: The hostname of the URL (e.g. 'example.com').

  • port: The port of the URL (e.g. '8080').

  • pathname: The path of the URL (e.g. '/index.html').

  • search: The query string of the URL (e.g. '?key=value').

Methods

The URL class also has several methods that can be used to manipulate URLs:

  • toString(): Returns the complete URL string.

  • searchParams: Returns a URLSearchParams object that can be used to set and get query parameters.

  • toJSON(): Returns a JSON representation of the URL.

Applications

The URL class is useful for any application that needs to work with URLs. For example:

  • Parsing and validating URLs.

  • Manipulating URLs (e.g. changing the protocol or hostname).

  • Generating URLs based on user input.

  • Comparing URLs for equality or similarity.


URLSearchParams Object

URLSearchParams is like a little bag that holds key-value pairs of information. It's used when you want to send some extra details along with a URL.

Simplified Explanation:

Imagine you're sending a message to a friend. You could write the message in the URL like this: example.com/send-message?message=Hello. But what if you want to send more than just the message? That's where URLSearchParams comes in. You can add extra information as key-value pairs, like this: example.com/send-message?message=Hello&name=John.

Code Example:

// Create a URLSearchParams object
const params = new URLSearchParams();

// Add key-value pairs
params.append("message", "Hello");
params.append("name", "John");

// Get the URL with the added parameters
const url = "example.com/send-message?" + params.toString();

console.log(url); // "example.com/send-message?message=Hello&name=John"

Real-World Application:

  • Filtering search results by adding parameters to a search URL.

  • Customizing the URL for tracking website analytics.


WebAssembly

What is WebAssembly?

Imagine you have a computer that can only understand a specific language, like English. But what if you want to run a program that's written in Spanish? You need a translator, right?

That's where WebAssembly (WASM) comes in. It's a special translator that allows web browsers to understand and run code that's written in other languages, like C++, Rust, or Go.

What are the benefits of using WebAssembly?

  • Faster performance: WASM is optimized for speed, so it can make web applications run faster.

  • Smaller file sizes: WASM files are usually smaller than other types of code, which saves bandwidth and reduces loading times.

  • Security: WASM is designed to be secure, protecting web applications from malicious attacks.

How is WebAssembly used?

WASM is used in a variety of ways, including:

  • Building high-performance web games and simulations

  • Creating interactive data visualizations

  • Developing complex web applications

Real-world example:

One example of how WASM is used in the real world is the game "DOOM 3." The developers used WASM to port the game to the web, allowing players to experience the classic first-person shooter in their browser.

Potential applications:

WASM has the potential to revolutionize the way we build and experience web applications. It can be used to create faster, more immersive, and more secure web applications. As WASM continues to develop, we can expect to see even more innovative and groundbreaking uses for it.

Here is a simplified code example of how to use WebAssembly:

const wasmModule = await WebAssembly.compile(wasmCode);
const wasmInstance = await WebAssembly.instantiate(wasmModule);
const addFunction = wasmInstance.exports.add;
const result = addFunction(1, 2);
console.log(result); // prints 3

WebSocket

The WebSocket class represents a persistent connection with a server that allows for two-way communication using the WebSocket protocol.

Real World Complete Code Implementation and Example:

const WebSocket = require("ws");

// Create a WebSocket connection to a server
const ws = new WebSocket("ws://localhost:8080");

// Open the WebSocket connection
ws.on("open", () => {
  console.log("WebSocket connection opened");
});

// Send a message to the server
ws.send("Hello from the client");

// Listen for messages from the server
ws.on("message", (data) => {
  console.log("Received message from server:", data);
});

// Close the WebSocket connection
ws.on("close", () => {
  console.log("WebSocket connection closed");
});

Potential Applications in the Real World:

  • Real-time chat applications

  • Multiplayer online games

  • Live streaming platforms

  • Financial trading platforms


WritableStream

A WritableStream is a stream that you can write data to. It is like a pipe that you can send data through. Data is written to the stream in chunks, and the stream will buffer the chunks until they can be written to the underlying resource.

Creating a WritableStream

const stream = new WritableStream();

Writing to a WritableStream

stream.write('Hello, world!');

Closing a WritableStream

When you are finished writing to the stream, you should close it. This will flush any remaining data to the underlying resource and close the stream.

stream.close();

Events

WritableStreams emit the following events:

  • 'close': Emitted when the stream is closed.

  • 'error': Emitted when an error occurs.

  • 'finish': Emitted when all data has been written to the stream.

Applications

WritableStreams can be used in a variety of applications, such as:

  • Logging: You can write logs to a WritableStream and then pipe them to a file or console.

  • Data storage: You can write data to a WritableStream and then store it in a database or other data store.

  • Data processing: You can write data to a WritableStream and then process it in some way, such as by filtering or transforming it.

Example

The following example shows how to create a WritableStream and write some data to it.

const stream = new WritableStream();

stream.write('Hello, world!');
stream.close();

Class: WritableStreamDefaultController

This class is a browser-compatible implementation of the WritableStreamDefaultController interface. It provides a way to control a writable stream in a browser-compatible way.

This class has the following methods and properties:

  • abort()

    • Aborts the stream, signaling that no more data will be written.

  • error(error)

    • Emits an error on the stream.

  • write(chunk)

    • Writes a chunk of data to the stream.

  • close()

    • Closes the stream, signaling that no more data will be written.

  • desiredSize

    • A property that returns the amount of data that the stream is able to receive.

This class is used in the following way:

const stream = new WritableStream();
const controller = stream.getWriter();

controller.write("Hello, world!");
controller.close();

This example code will create a writable stream and write the string "Hello, world!" to it. The stream will then be closed.

Real World Applications

Writable streams can be used in a variety of applications, such as:

  • Writing data to a file

  • Sending data over a network

  • Logging data

  • Caching data


WritableStreamDefaultWriter: A class that provides a stream's writer, for writing data to a stream. It offers an easy way to write data to the stream while handling backpressure automatically.

How to use it:

// Create a new WritableStream.
const stream = new WritableStream();

// Get its writer.
const writer = stream.getWriter();

// Write some data to the stream.
writer.write("Hello, world!");

// Close the stream.
writer.close();

Real-world applications:

Example: Use WritableStreamDefaultWriter to implement data transfer between two web pages via the MessagePort API.

// Page 1:
const page1 = window.open();
const port1 = new MessagePort();
page1.postMessage({ port1 }, [port1]);

// Page 2:
const page2 = window.open();
const port2 = new MessagePort();
page2.postMessage({ port2 }, [port2]);

// Establish a connection between the two pages.
port1.addEventListener("message", (e) => {
  const { port2 } = e.data;
  const writer = port2.writable;

  // Write data to the other page.
  writer.write("Hello from Page 1!");
});