0% found this document useful (0 votes)
11 views

JS

The document provides a comprehensive guide to understanding and utilizing JavaScript methods by categorizing them into groups such as String, Array, Object, Math, and Date methods. It emphasizes the importance of grasping key concepts, practicing commonly used methods, and leveraging resources like cheat sheets and documentation. Additionally, it offers strategies for effective learning, including creating memory aids, engaging in hands-on projects, and participating in coding challenges.

Uploaded by

shreyas
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
11 views

JS

The document provides a comprehensive guide to understanding and utilizing JavaScript methods by categorizing them into groups such as String, Array, Object, Math, and Date methods. It emphasizes the importance of grasping key concepts, practicing commonly used methods, and leveraging resources like cheat sheets and documentation. Additionally, it offers strategies for effective learning, including creating memory aids, engaging in hands-on projects, and participating in coding challenges.

Uploaded by

shreyas
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 54

JAVA SCRIPT

Remembering all JavaScript methods can seem overwhelming because there are
so many! However, you don't need to memorize everything. Instead, focus on
understanding key concepts and patterns that will allow you to recall and look up
methods effectively. Here's a guide to help you:

1. Group Methods by Purpose


Organize JavaScript methods into categories based on what they do. Here are
some common groups:

String Methods
.toUpperCase() , .toLowerCase() , .trim() , .slice() , .split() , .includes() ,
.replace() , etc.

Array Methods
.push() , .pop() , .shift() , .unshift() , .splice() ,
, .filter() , .slice() , .map()

.reduce() , .forEach() , .find() , .indexOf() , .sort() , .reverse() , etc.

Object Methods
Object.keys() , Object.values() , Object.entries() , Object.assign() , Object.freeze() ,
etc.

Math Methods
Math.round() , Math.ceil() , Math.floor() , Math.random() , Math.max() , Math.min() , etc.

Date Methods
.getFullYear() , .getMonth() , .getDate() , .getTime() , .setDate() , .toISOString() , etc.

2. Understand Common Patterns


JavaScript methods often follow similar patterns. Once you learn the logic, it's
easier to guess or recall related methods.

String Methods

JAVA SCRIPT 1
They typically return a new string (e.g., .slice() , .replace() ) or a boolean
(e.g., .includes() , .startsWith() ).

Array Methods
Methods like .push() , .pop() , and .splice() modify the original array.

Methods like .map() , .filter() , and .slice() return a new array without
modifying the original one.

Math Methods
Math methods often take numbers as arguments and return a number (e.g.,
Math.max() or Math.round() ).

3. Practice Commonly Used Methods


You don’t need to memorize rarely-used methods right away. Focus on methods
you’ll use frequently in coding:

Strings: .slice() , .split() , .trim() , .replace()

Arrays: .map() , .filter() , .reduce() , .push() , .pop()

Objects: Object.keys() , Object.values() , Object.assign()

By using these in practice, they’ll become second nature over time.

4. Leverage Mnemonics or Short Notes


Create memory aids for frequently confused methods:

CRUD for Arrays:

push() (Add to end)

pop() (Remove from end)

shift() (Remove from start)

unshift() (Add to start)

"FMS" for String Methods:

F ilter with .slice()

M odify with .replace()

S earch with .includes()

JAVA SCRIPT 2
5. Learn by Doing
The best way to remember methods is to use them often. Build small projects that
require:

String manipulation

Array operations

Object traversal

For example:

Create a to-do list app (uses arrays and objects).

Build a word counter (uses strings and arrays).

6. Use Cheat Sheets


Keep a reference or a JavaScript cheat sheet nearby. Here’s a simple example:

String Methods Cheat Sheet


Method Description
.slice() Extracts a part of a string.
.split() Splits a string into an array.
.trim() Removes whitespace.
.replace() Replaces part of a string.
.includes() Checks if a substring exists.

Array Methods Cheat Sheet


Method Description
.push() Adds an element to the end.
.pop() Removes the last element.
.map() Transforms each element.
.filter() Filters elements by condition.
.reduce() Reduces array to a single value.

7. Rely on Documentation
Nobody remembers every method, not even experienced developers. Instead:

Use MDN (Mozilla Developer Network) as your go-to resource.

JAVA SCRIPT 3
Use browser DevTools to experiment with methods interactively.

8. Practice Daily with Small Challenges


Use platforms like:

JavaScript30 for real-world challenges.

LeetCode or HackerRank for algorithm challenges.

9. Remember What’s Searchable


In modern development, you only need to understand the basics and patterns.
When you encounter something unfamiliar, just Google it!

I understand now! You want a more detailed explanation of how to iterate over
each data structure with code examples in the second column. Here's the updated
table with detailed iteration examples:

Data Structure
How to Iterate Important Notes
(Example)

Arrays hold ordered


Using for...of loop: for (const values. They can be
item of array) { console.log(item); iterated directly using
Array [1, 2, 3] } Using .forEach() method: for...of or
array.forEach(item => { processed with
console.log(item); }) methods like
.forEach() .

Using for...of loop: for (const Sets store unique


value of set) { console.log(value); values. They don’t
Set new Set([1, 2,
} Using .forEach() method: allow duplicates, and
3])
set.forEach(value => { iteration retrieves
console.log(value); }) values only (no keys).

Using for...of loop: for (const Maps store key-value


[key, value] of map) {
pairs. Use .entries()
Map new Map([["a", console.log(key, value); } Using
to explicitly get key-
1], ["b", 2]]) .forEach() method:
value pairs as [key,
map.forEach((value, key) => {
value] .
console.log(key, value); })

Object {"a": 1, "b": Using for...in loop: for (const key Objects are not
2} in obj) { console.log(key, inherently iterable but

JAVA SCRIPT 4
obj[key]); } Using can be converted into
Object.entries() : for (const [key, arrays of key-value
value] of Object.entries(obj)) { pairs using
console.log(key, value); } Object.entries() .

Each object in the array


Using nested for...of loop: for can be accessed with a
Array of Objects (const obj of array) { for (const loop. Use
[{"a": 1}, {"b": 2}] [key, value] of Object.entries(obj)) Object.entries() for
{ console.log(key, value); } }
key-value pairs within
individual objects.

Arrays of key-value
Using Object.fromEntries() : const pairs (e.g., [[key1,
Array of Key-Value value1], [key2,
obj = Object.fromEntries(array); for
Pairs [["a", 1], ["b", (const [key, value] of value2]] ) can be
2]] Object.entries(obj)) { transformed into
console.log(key, value); }
objects using
Object.fromEntries() .

Using Object.entries() : const obj = Object.fromEntries()


Object.fromEntries(array); for
Object.fromEntries() converts an iterable of
(const [key, value] of
[["a", 1], ["b", 2]] key-value pairs (like
Object.entries(obj)) {
console.log(key, value); } arrays) into an object.

Using for...of loop: for (const


Custom iterables must
value of myNumbers()) {
define a
Custom Iterable console.log(value); } Using [Symbol.iterator]
function* myNumbers()
.next() method: const iter = method and return an
{ yield 1; yield 2; }
myNumbers();
iterator object
console.log(iter.next().value);
implementing next() .
console.log(iter.next().value);

Detailed Explanation for How to Iterate


1. Array ( [1, 2, 3] ):

Using for...of loop: Iterates through the elements of the array.

for (const item of array) {


console.log(item); // Outputs: 1, 2, 3
}

Using .forEach() : Iterates through the array, passing each item to a


callback function.

JAVA SCRIPT 5
array.forEach(item => {
console.log(item); // Outputs: 1, 2, 3
});

2. Set ( new Set([1, 2, 3]) ):

Using for...of loop: Iterates through the values of the set.

for (const value of set) {


console.log(value); // Outputs: 1, 2, 3
}

Using .forEach() : Iterates through the set, passing each value to a callback
function.

set.forEach(value => {
console.log(value); // Outputs: 1, 2, 3
});

3. Map ( new Map([["a", 1], ["b", 2]]) ):

Using for...of loop: Iterates through the key-value pairs in the map.

for (const [key, value] of map) {


console.log(key, value); // Outputs: a 1, b 2
}

Using .forEach() : Iterates through the map, passing each key and value to
a callback function.

map.forEach((value, key) => {


console.log(key, value); // Outputs: a 1, b 2
});

4. Object ( {"a": 1, "b": 2} ):

Using for...in loop: Iterates through the keys of the object.

for (const key in obj) {


console.log(key, obj[key]); // Outputs: a 1, b 2

JAVA SCRIPT 6
}

Using Object.entries() : Converts the object into an array of key-value pairs


and iterates over them.

for (const [key, value] of Object.entries(obj)) {


console.log(key, value); // Outputs: a 1, b 2
}

5. Array of Objects ( [{"a": 1}, {"b": 2}] ):

Using nested for...of loop: Iterates over the array, then uses
Object.entries() to iterate over each object's key-value pairs.

for (const obj of array) {


for (const [key, value] of Object.entries(obj)) {
console.log(key, value); // Outputs: a 1, b 2
}
}

6. Array of Key-Value Pairs ( [["a", 1], ["b", 2]] ):

Using Object.fromEntries() : Converts the array of key-value pairs into an


object, then iterates over the object using Object.entries() .

const obj = Object.fromEntries(array);


for (const [key, value] of Object.entries(obj)) {
console.log(key, value); // Outputs: a 1, b 2
}

7. Object.fromEntries() ( [["a", 1], ["b", 2]] ):

Using Object.entries() : Iterates over the object returned by


Object.fromEntries() .

const obj = Object.fromEntries(array);


for (const [key, value] of Object.entries(obj)) {
console.log(key, value); // Outputs: a 1, b 2
}

8. Custom Iterable ( function* myNumbers() { yield 1; yield 2; } ):

JAVA SCRIPT 7
Using for...of loop: Iterates over the custom iterable.

for (const value of myNumbers()) {


console.log(value); // Outputs: 1, 2
}

Using .next() method: Manually calls the next() method to retrieve the
next value from the iterable.

const iter = myNumbers();


console.log(iter.next().value); // Outputs: 1
console.log(iter.next().value); // Outputs: 2

Function Type Description Code Example Use Cases

Reusable
A function with
blocks of code,
a declared javascript<br>function greet() {
Named easily
name. Can be console.log("Hello!"); }
Function <br>greet(); referenced in
reused and
debugging or
referenced.
recursion.

A function Callback
without a javascript<br>const add = functionality or
Anonymous
name, often function(a, b) { return a + b; }; dynamically-
Function <br>console.log(add(2, 3));
assigned to assigned
variables. behaviors.

A concise
syntax for Simplified
defining callbacks or
javascript<br>const greet = () =>
Arrow Function functions. console.log("Hi!");<br>greet();
where this
Lexically binds binding is
this (useful in required.
callbacks).

Immediately Encapsulation,
A function that
Invoked javascript<br>(function() { avoiding
is invoked
Function console.log("IIFE executed!"); }) polluting the
immediately ();
Expression global
after definition.
(IIFE) namespace.

JAVA SCRIPT 8
Functions that Managing
can yield infinite
javascript<br>function* numbers()
multiple values sequences,
Generator { yield 1; yield 2; yield 3; }
using yield <br>for (let num of numbers()) lazy evaluation,
Function
and maintain console.log(num); or
state between asynchronous
calls. processes.
javascript<br>function
Object
Functions used Person(name) { this.name = name; }
Constructor creation, often
with new to <br>const person = new
Function Person("Alice"); as a precursor
create objects.
<br>console.log(person.name); to classes.

A function that javascript<br>const obj = { Encapsulation


Method is a property of greet() { console.log("Hello!"); } of functionality
};<br>obj.greet();
an object. within objects.

A function that
returns a
javascript<br>async function Asynchronous
Promise and
Async fetchData() { const data = await operations like
allows fetch('/api'); console.log(data);
Function API calls or
asynchronous }<br>fetchData();
reading files.
code with
await .

A function javascript<br>function
passed as an process(callback) { callback(); } Event handling,
Callback
argument to <br>process(() => asynchronous
Function console.log("Callback
another execution.
executed!"));
function.

Solving
problems with
javascript<br>function
recursive
Recursive A function that factorial(n) { return n === 1 ? 1
: n * factorial(n - 1); } structures,
Function calls itself.
<br>console.log(factorial(5)); such as
factorial or tree
traversal.

A function that
Functional
takes another javascript<br>function
programming
Higher-Order function as an higherOrder(func) { func(); }
constructs like
Function argument or <br>higherOrder(() =>
console.log("Hello from HOF!")); map , reduce ,
returns a
and filter .
function.

Default A function that javascript<br>function greet(name Simplifies


= "Guest") { console.log(`Hello,
Parameter uses default handling of
${name}!`); }<br>greet();
Function parameter <br>greet("Alice");

JAVA SCRIPT 9
values if no optional
arguments are parameters.
passed.

A function that
Aggregating or
takes an javascript<br>function
processing a
Rest Parameter indefinite sum(...nums) { return
variable
Function number of nums.reduce((a, b) => a + b, 0); }
<br>console.log(sum(1, 2, 3)); number of
arguments
inputs.
using ... .

A function that
retains access javascript<br>function outer() {
to its outer const a = 10; return function Encapsulation,
Closure
scope variables inner() { console.log(a); }; } maintaining
Function <br>const innerFunc = outer();
even after the private state.
<br>innerFunc();
outer function
has executed.

Object-oriented
A function javascript<br>class Person {
programming;
defined inside greet() { console.log("Hi!"); } }
Class Method <br>const p = new Person(); grouping
a JavaScript
<br>p.greet(); behavior inside
class.
classes.

Utility
functions,
A function javascript<br>class MathUtil {
shared
bound to a static add(a, b) { return a + b; }
Static Method }<br>console.log(MathUtil.add(2, methods that
class, not an
3)); don't depend
instance.
on class
instances.

Functional
A function that programming
breaks down javascript<br>const add = a => b for creating
Currying
into multiple => a + b;<br>console.log(add(2) reusable,
Function (3));
unary partially-
functions. applied
functions.

A function that
Handling
returns a javascript<br>function asyncTask()
asynchronous
Promise Promise for { return new Promise(resolve =>
resolve("Task complete!")); } tasks, chaining,
Function handling
<br>asyncTask().then(console.log); and avoiding
asynchronous
callback hell.
tasks.

JAVA SCRIPT 10
Short, inline
An unnamed
operations
Anonymous arrow function, javascript<br>[1, 2, 3].map(num =>
such as in
Arrow Function often used num * 2);
map , filter ,
inline.
and reduce .

Notes:
1. Functions like closures, IIFE, and higher-order functions are fundamental for
advanced JavaScript concepts.

2. Use the appropriate function type depending on your use case, readability,
and maintainability of the code.

Here’s a detailed note with colorful bullets and structured content based on your
explanation of JavaScript's array functions (map, filter, reduce):

Introduction to Array Functions in JavaScript

Map Function: Transformation of Arrays


🔵 What is the Array.map() function?

The map() function is used to transform the elements of an array.

It returns a new array after applying a transformation to each element.

🔴 Example Transformation Types:


Doubling: Each value is doubled.

Tripling: Each value is tripled.

Binary Conversion: Each value is converted to binary.

How to Use the map() Function:


1. Creating an Example:

const output = ARR.map(transformation);

2. Doubling Values:

Write a function to double values and pass it to the map() :

JAVA SCRIPT 11
function double(x) {
return x * 2;
}
const output = ARR.map(double);
console.log(output); // Output: [10, 6, 12]

3. Tripling Values:

Similarly, you can triple the values by changing the function:

function triple(x) {
return x * 3;
}
const output = ARR.map(triple);
console.log(output); // Output: [15, 9, 18]

4. Binary Transformation:

Use the .toString(2) method to convert numbers to binary:

function toBinary(x) {
return x.toString(2);
}
const output = ARR.map(toBinary);
console.log(output); // Output: ['101', '110', '111']

or

🔵 Alternative Syntax Using Arrow Functions:


You can directly use arrow functions within the map() method:

const output = ARR.map(x => x * 2); // Doubling each valu


e
console.log(output); // Output: [10, 6, 12]

JAVA SCRIPT 12
Filter Function: Filtering Arrays
🔵 What is the Array.filter() function?

filter() is used to filter out values from an array based on a condition.

It returns a new array containing only the elements that satisfy the condition.

Examples of Filtering:
Filtering Odd Numbers:

function isOdd(x) {
return x % 2 !== 0;
}
const output = ARR.filter(isOdd);
console.log(output); // Output: [5, 3]

Filtering Even Numbers:

function isEven(x) {
return x % 2 === 0;
}
const output = ARR.filter(isEven);
console.log(output); // Output: [2, 6]

Filtering Numbers Greater Than 4:

const output = ARR.filter(x => x > 4);


console.log(output); // Output: [5, 6]

🔴 Quick Example with Arrow Functions:


Arrow functions simplify syntax:

const output = ARR.filter(x => x % 2 === 0); // Even numb


ers
console.log(output); // Output: [2, 6]

Reduce Function: Accumulating Values


🔵 What is the Array.reduce() function?

JAVA SCRIPT 13
reduce() iterates over the array and accumulates a single result.

It’s used when you need to combine elements into a single value (e.g.,
summing, finding max).

How to Use the reduce() Function:


1. Basic Syntax:

const output = ARR.reduce((accumulator, currentValue) => {


return accumulator + currentValue;
}, initialValue);

2. Sum of Elements:

const sum = ARR.reduce((acc, curr) => acc + curr, 0);


console.log(sum); // Output: 17

3. Finding Maximum Value:

const max = ARR.reduce((acc, curr) => (curr > acc ? curr :


acc), 0);
console.log(max); // Output: 6

🔴 Explaining accumulator and currentValue :

Accumulator: Stores the accumulated result (e.g., sum or max).

CurrentValue: The current element being processed in the iteration.

Advanced reduce() Example:

Find Maximum Value Using reduce() :


1. Using Traditional Loop to Find Maximum:

function findMax(arr) {
let max = 0;
for (let i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}

JAVA SCRIPT 14
}
return max;
}
console.log(findMax(ARR)); // Output: 6

2. Using reduce() to Find Maximum:

const maxValue = ARR.reduce((max, curr) => (curr > max ? c


urr : max), 0);
console.log(maxValue); // Output: 6

Summary of JavaScript Array Functions


🔵 : Transforms elements of the array into a new array based on a
map()

specified function (e.g., doubling, tripling).

🔴 filter() : Filters elements of the array based on a condition (e.g., even


numbers, values greater than 4).

🟢 reduce() : Accumulates values from the array into a single result (e.g., sum,
maximum).

In this set of examples, you've been exploring the core functions of JavaScript:
map() , reduce() , and filter() , focusing on how to manipulate and process data

arrays, often containing objects, in real-world scenarios.

Example 9 - Using map() :


In this example, you're tasked with generating a list of full names from an array of
user objects. Each object contains properties like first name , last name , and age .
The map() function is perfect here because you want to transform each object into
a string (the full name).

const users = [
{ firstName: 'AI', lastName: 'Smith', age: 26 },
{ firstName: 'Donald', lastName: 'Trump', age: 75 },
{ firstName: 'John', lastName: 'Doe', age: 50 }
];

const fullNames = users.map(user => `${user.firstName} ${use

JAVA SCRIPT 15
r.lastName}`);
console.log(fullNames);

This code outputs:


["AI Smith", "Donald Trump", "John Doe"]

Here, map() is used to iterate over each object in the array and return a new array
of full names by concatenating the firstName and lastName .

Example 10 - Using reduce() for a Count:


Next, you're asked to find the count of users based on their unique ages. Here,
the reduce() function is the right tool to use because you're reducing the array to a
single value: an object that maps age to count.

const users = [
{ firstName: 'AI', lastName: 'Smith', age: 26 },
{ firstName: 'Donald', lastName: 'Trump', age: 75 },
{ firstName: 'John', lastName: 'Doe', age: 50 },
{ firstName: 'Jane', lastName: 'Doe', age: 26 }
];

const ageCount = users.reduce((accumulator, user) => {


accumulator[user.age] = (accumulator[user.age] || 0) + 1;
return accumulator;
}, {});

console.log(ageCount);

This code outputs:


{ 26: 2, 75: 1, 50: 1 }

JAVA SCRIPT 16
Here, reduce() iterates over each user object and adds the age to the accumulator
object, keeping track of the count of each unique age.

Example 11 - Chaining map() , filter() , and reduce() :


You explored the power of chaining functions like map() , filter() , and reduce() .
For instance, when filtering out users under the age of 30 and getting their first
names:

const users = [
{ firstName: 'AI', lastName: 'Smith', age: 26 },
{ firstName: 'Donald', lastName: 'Trump', age: 75 },
{ firstName: 'John', lastName: 'Doe', age: 50 },
{ firstName: 'Jane', lastName: 'Doe', age: 29 }
];

const firstNamesUnder30 = users


.filter(user => user.age < 30)
.map(user => user.firstName);

console.log(firstNamesUnder30);

This code outputs:


["AI", "Jane"]

Here, filter() is used to select users under 30, and map() is then used to extract
the first names of these users.

Homework Challenge:
You were also tasked with achieving the same result (first names of users under
30) using only reduce() instead of filter() and map() combined. This challenge
helps reinforce the power of reduce() to handle complex transformations.

const firstNamesUnder30WithReduce = users.reduce((accumulato


r, user) => {
if (user.age < 30) {
accumulator.push(user.firstName);
}
return accumulator;
}, []);

JAVA SCRIPT 17
console.log(firstNamesUnder30WithReduce);

This code also outputs:


["AI", "Jane"]

By using reduce() , you're iterating through the array and accumulating the first
names of users whose age is below 30.

Key Takeaways:
map()is used for transforming an array by applying a function to each element
and returning a new array.

reduce() is used for reducing an array to a single value (often an object) by


iterating over each element.

filter()is used to create a new array with elements that pass a specific
condition.

Chaining these functions allows you to perform complex data transformations


in a clean and functional way.

🎉Understanding
Welcome Back to Namaste JavaScript - Episode 1:
Callbacks in JavaScript

💥 Episode Overview
In this first episode, we’re going to understand the core concept of callbacks in
JavaScript. We'll explore:

The Good Parts ✅


The Bad Parts ❌

✨ The Good Parts of Callbacks


JAVA SCRIPT 18
🔑 What are Callbacks?
Definition: A callback is a function that you pass into another function, and
this callback function is executed at a later time, once an event or action is
complete. It essentially allows you to "wait" for some process to finish before
continuing to the next task.

Why are Callbacks Important?

JavaScript is an asynchronous programming language, meaning it allows


you to execute code in parallel or with delays. However, JavaScript is also
single-threaded, meaning only one task can be executed at a time. To
manage multiple tasks that take time (like fetching data, waiting for user
input, etc.), callbacks help in managing these asynchronous tasks by
allowing you to schedule the function to run after the task completes.

💡 Example: Simple Asynchronous Callback


Let’s say you want to print a message after a delay. You can use the setTimeout

function, which takes a callback function and a delay as arguments.

console.log("Hello, World!"); // First, this prints immediat


ely

setTimeout(() => {
console.log("This prints after 3 seconds!"); // This will
be delayed
}, 3000); // 3000 milliseconds (3 seconds)

console.log("This prints immediately after the first line");

Expected Output:

Hello, World!
This prints immediately after the first line
This prints after 3 seconds!

Explanation:

The setTimeout function sets up a timer to execute the callback function


(i.e., () => { console.log(...) } ) after 3000 milliseconds (3 seconds).

JAVA SCRIPT 19
During this time, the JavaScript engine continues executing the rest of the
code. After the delay, the callback is invoked, printing the final message.

🌍 Real-World Example: E-commerce Flow


Let’s consider an e-commerce website where the user follows this flow:

1. Create an Order: The user adds items to the cart, and an order is created.

2. Proceed to Payment: After the order is created, the user proceeds to


payment.

3. Show Order Confirmation: Once payment is confirmed, the order summary is


shown.

Here, we need to ensure each task happens in sequence, and callbacks are
perfect for managing this.

Code Example:

function createOrder(cartItems, callback) {


console.log("Creating order with items:", cartItems);
callback(); // Calls the next step (proceeding to payment)
}

function proceedToPayment() {
console.log("Proceeding to payment...");
}

const cartItems = ['Shoes', 'Shirt', 'Jeans'];


createOrder(cartItems, proceedToPayment); // After order cre
ation, proceed to payment

Flow:

1. The createOrder function is executed first.

2. Once the order creation is complete, it triggers the proceedToPayment

function (callback).

💡 Why Use Callbacks Here?


In this case, the order creation happens first. Once the order is created, we
proceed to payment only after the creation process is completed. If we didn't use
a callback, both actions could happen at the same time, causing confusion or
errors.

JAVA SCRIPT 20
⚡ The Bad Parts of Callbacks
1. Callback Hell (Pyramid of Doom)
What is Callback Hell?

Callback Hell refers to a situation where you have multiple nested


callbacks, making the code hard to read, maintain, and debug. This
happens especially when you need to execute several asynchronous tasks
that depend on each other in sequence. This structure also known as
pyramid of doom

🌍 Example: E-commerce Flow with Multiple Callbacks


Imagine we want to handle multiple tasks in the e-commerce website flow, such
as:

1. Create Order

2. Proceed to Payment

3. Show Order Summary

4. Update Wallet

Without using Promises, we might end up with a deeply nested structure of


callbacks.

JAVA SCRIPT 21
createOrder(cartItems, (order) => {
proceedToPayment(order, (paymentStatus) => {
showOrderSummary(paymentStatus, (summary) => {
updateWallet(summary, (walletStatus) => {
console.log("Process Complete!");
});
});
});
});

Problem:

This results in nested functions, and it becomes very difficult to read,


especially when the sequence becomes longer.

It's called the Pyramid of Doom because the code looks like a pyramid,
making it harder to manage and understand.

JAVA SCRIPT 22
Why is it bad?
Increased Complexity: Each time you add more asynchronous tasks, the level
of nesting increases, making the code harder to debug and maintain.

Hard to Track: You have to track each function call and its associated
callback. This can get confusing when the logic becomes complex.

2. Inversion of Control
What is Inversion of Control?

Inversion of Control (IoC) refers to a situation where you give control of


the flow of execution to another function, usually by passing a callback.
This can lead to situations where your program's flow becomes
unpredictable or difficult to manage.

🚨 Example: Order Process with IoC


In the following example, we depend on the createOrder function to execute the
callback when the order is created:

function createOrder(cart, callback) {


console.log("Order Created with items:", cart);
// What if the callback is not executed properly?
callback(); // This may or may not happen!
}

function proceedToPayment() {

JAVA SCRIPT 23
console.log("Payment Successful!");
}

createOrder(cartItems, proceedToPayment); // Callback may no


t be called correctly!

Problem:

If the callback function inside createOrder is missing, or executed multiple


times by accident, we lose control over the execution flow, leading to
potential bugs or unexpected behavior.

📌 Key Takeaways
1. Good Parts of Callbacks ✅:
Callbacks help manage asynchronous tasks by allowing us to define
actions after the completion of a task (e.g., setTimeout ).

Example: Order Creation → Proceed to Payment.

They enable tasks like handling user input, API calls, or delayed actions
in JavaScript.

2. Bad Parts of Callbacks ❌:


Callback Hell: When you nest multiple callbacks, the code becomes
complex and difficult to maintain.

Inversion of Control: Passing callbacks can sometimes cause


unpredictable behavior, where the program’s flow depends on external
functions.

🎯 Conclusion and Homework


Recap: Today, we learned that callbacks are a powerful tool for handling
asynchronous tasks. However, when used improperly, they can lead to
callback hell and loss of control.

Homework:

1. Like the video if you found it useful!

2. Share it with your friends so they can understand callbacks too!

3. Comment: Share your thoughts about the problems with callbacks and
how they could be avoided!

JAVA SCRIPT 24
Introduction to Promises in JavaScript
Promises are essential in modern JavaScript, especially for handling
asynchronous operations. If you're aiming to become proficient in JavaScript,
particularly for frontend development, understanding Promises is critical. They
are commonly asked about in interviews and will make you a better developer.
In this video, we dive deep into the beauty of Promises. Rather than just
explaining them quickly, we'll take our time to explore how they work, how they
solve problems in asynchronous code, and why they are such a game-changer for
JavaScript developers.

💥 Code Example: Callbacks vs Promises


We'll take a practical example of an e-commerce website like Amazon and see
how we handle asynchronous operations before and after Promises.

1. The Scenario:

We have a cart with items such as shoes, pants, and kurta.

Two APIs:

Create Order API: Takes the cart items and returns an order ID.

Proceed to Payment API: Takes the order ID and processes the


payment.

Both APIs are asynchronous, meaning they take some time to execute and
we don't know how long.

⏳ Using Callbacks to Handle Asynchronous Operations


Using Callbacks (Traditional Approach)
Before Promises, we used callbacks to handle asynchronous code. Let's see how
that would look for the create order and proceed to payment APIs:

const cart = ['Shoes', 'Pants', 'Kurta'];

// Create Order API - Takes cart items and returns an order I


D
function createOrder(cart, callback) {

JAVA SCRIPT 25
// Simulating async order creation (it might take time)
setTimeout(() => {
const orderId = '12345';
callback(orderId); // Callback is invoked with order
ID once order is created
}, 2000); // Simulating async operation delay
}

// Proceed to Payment API - Takes order ID and processes paym


ent
function proceedToPayment(orderId) {
console.log(`Proceeding to payment with order ID: ${order
Id}`);
}

createOrder(cart, proceedToPayment);

Explanation:

createOrderis asynchronous, and it calls the callback function with the


order ID once the order is created.

We "pass" the proceedToPayment function as a callback to createOrder , which


gets executed after the order is created.

Problem: Inversion of Control


In this setup, we pass the callback function to createOrder , essentially giving
control of our code to the createOrder function.

This creates a potential problem: What if the callback is never called or called
multiple times? It’s risky to rely on another part of the code to call our callback
correctly, especially when we have no control over it.

🔑 Introducing Promises: A Better Solution


The Promise Approach
Instead of passing a callback, we can return a Promise from the createOrder API. A
Promise is an object that represents the eventual completion (or failure) of an
asynchronous operation and its resulting value.
Let's refactor the previous code to use Promises:

JAVA SCRIPT 26
const cart = ['Shoes', 'Pants', 'Kurta'];

// Create Order API - Returns a Promise


function createOrder(cart) {
return new Promise((resolve, reject) => {
setTimeout(() => {
const orderId = '12345';
resolve(orderId); // Promise is resolved with or
der ID
}, 2000); // Simulating async operation delay
});
}

// Proceed to Payment API - Takes order ID and processes paym


ent
function proceedToPayment(orderId) {
console.log(`Proceeding to payment with order ID: ${order
Id}`);
}

createOrder(cart)
.then(proceedToPayment) // Once promise is resolved, pro
ceed to payment
.catch(error => console.log(error)); // Handle any error
s

Explanation:

createOrder now returns a Promise instead of using a callback.

is called when the order is successfully created, which fills


resolve(orderId)

the Promise with the order ID.

The then method is used to attach a callback function ( proceedToPayment ) to


the Promise, which will be executed once the Promise is resolved.

If any error occurs during the asynchronous operation, it will be handled in


the catch block.

JAVA SCRIPT 27
✅ Why Promises Are Better
1. Improved Control
With Promises, we don't pass our callback to another function. Instead, we
attach it to a Promise, giving us more control over when the callback gets
called.

The Promise guarantees that it will resolve or reject exactly once — and it will
automatically call the .then() method when the data is available.

2. Cleaner Code
Promises eliminate the callback hell (nested callbacks), leading to cleaner,
more readable code.

It also separates concerns, where the function creates the order and returns a
Promise, and we control how to handle the result using .then() .

3. Avoiding Callback Issues


Callbacks may be called multiple times or never at all, but Promises guarantee
that they will resolve only once and always execute the then method when
they are ready.

Promises offer a reliable mechanism for handling asynchronous data,


reducing risks associated with inversion of control.

📦 Real Promise Object in Action (Using Fetch API)


Let’s dive into the actual Promise object returned by APIs like fetch :

JAVA SCRIPT 28
// Using the fetch API to get data from GitHub
fetch('https://api.github.com/users/yourUsername')
.then(response => response.json()) // Parse the JSON res
ponse
.then(data => console.log(data)) // Log the user data
.catch(error => console.error(error)); // Handle errors

Explanation:

fetch returns a Promise that represents the result of an HTTP request.

When the request is completed, the Promise is fulfilled, and the .then()

method is triggered.

If an error occurs (like a network failure), it will be handled by the .catch()

block.

Promise States
Pending: The Promise is still waiting for a result (e.g., when making an API
request).

Fulfilled: The Promise has completed successfully and holds the data.

Rejected: The Promise was unsuccessful and holds an error message.

You can explore the actual Promise object in the browser’s developer tools to see
its states ( pending , fulfilled , rejected ) and results.

🎯 Key Takeaways
Promises are a more reliable and cleaner way to handle asynchronous
operations compared to callbacks.

They provide control over the flow of the program, ensuring that callbacks are
executed only when the data is ready.

With Promises, we avoid the issues of inversion of control and callback hell,
making our code more readable and maintainable.

📚 What’s Next?
In the next video, we'll explore how to chain Promises and handle more complex
asynchronous workflows efficiently, as well as how to use async/await to simplify
Promises even further!

JAVA SCRIPT 29
Promise States
A Promise in JavaScript can have one of three states:

1. Pending ( 🔵) – The promise is still in progress, not yet resolved or rejected.


2. Fulfilled (🟢) – The promise has been successfully completed with a result.

3. Rejected (🔴) – The promise failed to complete, usually due to an error.

Example:
When a fetch request is made, the returned promise will initially be in the pending
state. After a certain amount of time, if the request succeeds, it transitions to
fulfilled. If there’s an error, it becomes rejected.

let user = fetch('https://api.example.com/user');


console.log(user); // Logs: Promise {<pending>}

Why does it show pending?

When the code runs, JavaScript does not wait for the fetch to complete and
immediately moves to the next line. It logs the promise in its pending state.
This is because fetching data is an asynchronous operation. The promise will
eventually resolve when the data is fetched.

Promise Chaining
Promises also allow you to chain multiple operations, so they can be executed in
sequence. Instead of nesting callbacks (which leads to "callback hell"), promises
allow for cleaner, more readable code.

Example:
Here’s a flow where multiple dependent actions are performed:

1. Create an order.

2. Proceed with payment.

3. Show order summary.

4. Update wallet balance.

JAVA SCRIPT 30
or using Arrow fuc

createOrder()
.then(order => proceedToPayment(order))
.then(paymentInfo => showOrderSummary(paymentInfo))
.then(summary => updateWalletBalance(summary))
.catch(error => console.log('Error:', error));

This Promise chaining is preferred over traditional callbacks because it avoids the
"Pyramid of Doom" or callback hell.

Handling Data in Chained Promises

JAVA SCRIPT 31
Each .then() in the chain handles the data returned by the previous one. If we
forget to return a promise inside a .then() , it can break the chain and data won’t
pass through correctly.

Example:

createOrder()
.then(order => {
return proceedToPayment(order); // Ensure to return the p
romise
})
.then(payment => showOrderSummary(payment))
.catch(error => console.log('Error:', error));

The Importance of Promises


1. Avoid Inversion of Control: You control when the callback is called, not
another API or function.

2. Guaranteed Completion: Promises can only be resolved once, ensuring


predictable and reliable behavior.

3. Immutable Data: Once a promise is resolved, the data it contains cannot be


altered.

4. Cleaner Code: Promises allow asynchronous operations to be written in a


linear, readable, and manageable way, especially with chaining.

Interview Prep for Promises

What is a promise in JavaScript?


Simple definition: A Promise is an object that represents the eventual
completion (or failure) of an asynchronous operation and its resulting value. It
guarantees a result, either success or failure, at some point in the future.

Why do we use promises?


To handle asynchronous operations: Promises allow us to manage
asynchronous code more effectively, avoiding nested callbacks and ensuring
that we can handle success and failure cases properly.

Better error handling: With .catch() , we can handle errors at the end of a
chain, improving the structure and readability of our code.

JAVA SCRIPT 32
By using promises, JavaScript developers can handle asynchronous tasks without
the headaches of callback hell, creating more reliable and maintainable code.

JAVA SCRIPT 33
Mastering JavaScript Promises: A
Comprehensive Guide with Examples
Promises are one of the most powerful concepts in JavaScript. They make
handling asynchronous operations cleaner and more readable. In this guide, we’ll

JAVA SCRIPT 34
dive deep into how to create and consume promises, handle errors, and perform
promise chaining. By the end, you’ll have the confidence to write and use
promises effectively.

Understanding the Basics


What is a Promise?
A promise is an object representing the eventual completion (or failure) of an
asynchronous operation. It can be in one of three states:

Pending: The operation is not yet complete.

Resolved (Fulfilled): The operation completed successfully.

Rejected: The operation failed.

Consuming Promises
Example: E-commerce Order Flow
Let’s consider an e-commerce website where you need to create an order based
on cart items and then proceed to payment.

Workflow:
1. Create an order using the cart items.

2. Receive an orderID .

3. Use the orderID to proceed to payment.

Code to Consume Promises:

const cart = ["shoes", "pants", "t-shirt"];

createOrder(cart)
.then(orderID => {
console.log("Order created with ID:", orderID);
return proceedToPayment(orderID);
})
.then(paymentInfo => {
console.log("Payment successful:", paymentInfo);
})

JAVA SCRIPT 35
.catch(error => {
console.error("Error:", error.message);
});

Creating Promises
To understand promises better, let’s create one from scratch.

Producer Code: createOrder

function createOrder(cart) {
return new Promise((resolve, reject) => {
// Validate the cart
if (!validateCart(cart)) {
return reject(new Error("Cart is not valid"));
}

// Simulate an async operation


setTimeout(() => {
const orderID = "12345"; // Simulated order ID
resolve(orderID);
}, 5000); // Simulate 5 seconds delay
});
}

function validateCart(cart) {
return cart.length > 0;
}

function proceedToPayment(orderID) {
return new Promise((resolve, reject) => {
// Simulate async payment processing
setTimeout(() => {
resolve(`Payment processed for order ${orderID}`);
}, 3000);
});
}

JAVA SCRIPT 36
Error Handling
Graceful Error Handling
Errors should always be handled gracefully to prevent application crashes. Use
.catch() for handling errors in promises.

Example:

createOrder([]) // Invalid cart


.then(orderID => {
console.log("Order created with ID:", orderID);
})
.catch(error => {
console.error("Error encountered:", error.message);
});

Output:

Error encountered: Cart is not valid

Promise Chaining
Concept
Promise chaining allows multiple asynchronous tasks to be performed
sequentially, where the output of one is the input to the next.

Example: Extending the Order Flow

createOrder(cart)
.then(orderID => {
console.log("Order created with ID:", orderID);
return proceedToPayment(orderID);
})
.then(paymentInfo => {
console.log("Payment successful:", paymentInfo);
return sendConfirmationEmail(paymentInfo);
})
.then(emailStatus => {

JAVA SCRIPT 37
console.log("Confirmation email sent:", emailStatus);
})
.catch(error => {
console.error("Error:", error.message);
});

function sendConfirmationEmail(paymentInfo) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(`Email sent for payment: ${paymentInfo}`);
}, 2000);
});
}

Key Takeaways
1. Creating Promises: Use the Promise constructor with resolve and reject to
create custom promises.

2. Consuming Promises: Use .then() for handling successful operations and


.catch() for errors.

3. Error Handling: Always handle errors gracefully to avoid unhandled promise


rejections.

4. Chaining: Use promise chaining for sequential execution of asynchronous


tasks.

Advanced Topics
Promise.all : Handle multiple promises concurrently.

Promise.race : Resolve as soon as the fastest promise settles.

async/await : Syntactic sugar for working with promises in an easier-to-read


manner.

Final Words: Mastering promises is essential to becoming a confident JavaScript


developer. Practice creating and consuming promises to solidify your
understanding.

Here’s a detailed breakdown of Advanced Promise Chaining and Error Handling


using color-coded bullet points for clarity:

JAVA SCRIPT 38
🔵 Promise Chaining Concept
Promise chaining allows you to run multiple asynchronous tasks in a
sequence, passing data from one step to the next.

You return the result of each asynchronous operation to the next .then()

block, ensuring the data flows smoothly through the chain.

Example:

createOrder()
.then(orderId => proceedToPayment(orderId))
.then(paymentInfo => showOrderSummary(paymentInfo))
.then(walletInfo => updateWallet(walletInfo))
.catch(error => handleError(error));

🔴 Common Mistake in Promise Chaining


Developers sometimes forget to return the result of one promise so that the
next step can use the data.

Important: Always return data or promises within .then() to pass it down


to the next step.

Example of mistake:

createOrder()
.then(() => proceedToPayment()) // No return here
.then(paymentInfo => logInfo(paymentInfo));

🟢 How to Correctly Chain Promises


Ensure that each .then() returns something, whether it’s a value or a promise.

Corrected Example:

createOrder()
.then(orderId => {
return proceedToPayment(orderId); // Return the pr
omise
})
.then(paymentInfo => {
return showOrderSummary(paymentInfo); // Return th

JAVA SCRIPT 39
e next promise
})
.then(walletInfo => {
return updateWallet(walletInfo); // Return the nex
t promise
});

🔵 Promise Hell (Callback Hell for Promises)


If you don’t return promises and just keep nesting .then() callbacks, the code
becomes messy and hard to maintain (referred to as "Promise Hell").

Bad Example (Promise Hell):

createOrder()
.then(() => proceedToPayment())
.then(() => showOrderSummary())
.then(() => updateWallet());

🔴 Advanced Error Handling


Use .catch() at the end of the chain to handle any errors that occur in the
chain.

Global Catch Example:

createOrder()
.then(orderId => proceedToPayment(orderId))
.then(paymentInfo => showOrderSummary(paymentInfo))
.catch(error => {
console.error('Error:', error);
// Handle error gracefully
});

🟢 Handling Errors at Specific Steps


You can also place .catch() at specific steps to catch errors only for certain
parts of the chain.

Specific Catch Example:

JAVA SCRIPT 40
createOrder()
.then(orderId => proceedToPayment(orderId))
.catch(error => {
console.error('Error in payment:', error);
})
.then(paymentInfo => showOrderSummary(paymentInfo));

🔵 Handling Errors Gracefully


If you want to continue the chain even after an error occurs, use a .catch() in
a specific part of the chain to handle the error and allow subsequent steps to
continue.

Example (Error in Cart Validation, Continue Payment Process):

createOrder()
.then(orderId => proceedToPayment(orderId))
.catch(error => {
console.error('Error with order:', error); // Hand
les cart error
})
.then(() => showOrderSummary()) // Continue if cart
validation fails
.then(() => updateWallet());

🔴 catch and .then() Relationship


A .catch() only handles errors in the chain above it, not the ones below it.

After .catch() , you can always continue with .then() to execute further
operations.

Example:

createOrder()
.then(orderId => proceedToPayment(orderId))
.catch(error => {
console.error('Error in order:', error);
})
.then(() => showOrderSummary());

JAVA SCRIPT 41
🟢 Best Practices for Promise Handling
Keep the promise chain clean and readable by returning promises in each
.then() .

Handle errors locally if needed, using specific .catch() blocks, and ensure
that a generic .catch() is at the end of the chain to catch unforeseen errors.

Avoid "Promise Hell" by always returning values or promises.

🔵 Promise Summary Recap


1. Creating Promises:

Use the new Promise constructor to create promises, where you pass
resolve and reject functions.

You can only resolve a promise once.

2. Catching Errors:

Attach error handlers using .catch() to gracefully handle failures.

3. Chaining Promises:

Always return the result of each .then() to pass data to the next step.

4. Error Handling:

Handle errors globally at the end or locally at specific steps in the chain.

5. Avoiding Promise Hell:

Use clean chains with returns to avoid nested callbacks and make your
code easier to manage.

🟢 Teaser for Next Video:


The next video will dive deeper into combining multiple promises and
handling them together efficiently, especially when you need to resolve
multiple promises at once.

Homework Assignment:
Create a Promise chain involving four async APIs: createOrder , proceedToPayment ,
showOrderSummary , and updateWallet .

Handle errors appropriately and chain the promises in a logical order.

JAVA SCRIPT 42
This structured approach ensures that promises are used efficiently and helps
avoid common pitfalls in asynchronous programming.

Here is a detailed breakdown of the script, presented systematically with colorful


🚀✨
bullets and relevant code snippets to clarify each point.

🌟in JavaScript
Script Summary: Understanding async and await

🎥 Introduction
🟣 Welcome to Namaste JavaScript!
🟡 Today's focus is on one of the most awaited topics: async and await in
JavaScript.

Why Learn It?


✅ Essential for daily coding.
✅ Key for acing interviews.

Topics Covered:
🔵 What is
?
🔴 What is
async

?
🟢 Behind-the-scenes working.
await

🔵 Error handling in
/ .
🔴 Real-life examples.
async await

🟢 Comparison with
.then() and .catch() .

✨ 1. What is async ?
💡 Definition:
🔷 The keyword is used to define asynchronous functions.
async

JAVA SCRIPT 43
async function getData() {
return "Hello, Async!";
}

💡 Key Points:
1. 🟠 An function always returns a
async . Promise

2. 🟡 If a non-promise value is returned, JavaScript wraps it in a promise.

🎓 Code Example 1: Returning Non-Promise Value


async function getData() {
return "Namaste"; // Non-promise value
}

const data = getData();


console.log(data); // Output: Promise {<fulfilled>: "Namast
e"}

✅ Explanation:
The getData function returns "Namaste" , which is wrapped in a promise.

🎓 Code Example 2: Returning a Promise


async function getPromise() {
return Promise.resolve("Resolved Value");
}

const data = getPromise();


data.then(console.log); // Output: "Resolved Value"

✅ Explanation:
If an explicit promise is returned, it is passed as-is, not re-wrapped.

✨ 2. Using await with async


💡 Definition:

JAVA SCRIPT 44
🔷 The await keyword pauses the execution of the async function until the
promise resolves.

async function handlePromise() {


const result = await Promise.resolve("Awaited Result");
console.log(result); // Output: "Awaited Result"
}
handlePromise();

💡 Key Points:
1. 🟢 can only be used inside an
await function.
async

2. 🟡 It pauses the execution until the promise resolves.

3. 🟠 Improves readability compared to chaining.


.then()

🎓 Code Example 3: Awaiting Multiple Promises


async function fetchData() {
const data1 = await Promise.resolve("Data 1");
const data2 = await Promise.resolve("Data 2");
console.log(data1, data2); // Output: "Data 1", "Data 2"
}
fetchData();

✅ Explanation:
Sequentially handles promises, improving code clarity.

✨ 3. Comparing .then() and async/await

Feature .then() and .catch() async/await

Nested and harder to follow for


Readability Clear and linear flow
complex logic

Can use try-catch inside the


Error Handling Requires separate .catch() blocks
function

Ease of More difficult to trace through Easier due to synchronous


Debugging promise chains appearance

🎓 Example Comparison
JAVA SCRIPT 45
🟢 Using .then()

fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));

🔵 Using async/await

async function fetchData() {


try {
const response = await fetch('https://api.example.co
m/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error(error);
}
}
fetchData();

✅ Which is better?
For complex chains, async/await is more readable and maintainable.

✨ 4. Error Handling in async/await


💡 Handling Errors: Use try-catch blocks to catch errors during asynchronous
operations.

async function fetchData() {


try {
const response = await fetch('https://api.example.co
m/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.error("Error fetching data:", error);
}

JAVA SCRIPT 46
}
fetchData();

✅ Benefits:
1. 🟠 Centralized error handling.

2. 🟡 Cleaner structure compared to .catch() chaining.

✨ 5. Common Interview Questions


1. What does async do?
🟢 It marks a function as asynchronous and ensures it returns a promise.
2. What is await used for?
🔵 It pauses the function execution until a promise resolves.
3. Can await be used outside async functions?
🔴 No, it throws a syntax error.
4. Difference between .then() and async/await ?
🟠 .then()chains promises, while async/await provides a synchronous-like
syntax for handling promises.

🎯 Conclusion:
The combination of async and await simplifies asynchronous programming in
JavaScript, making code more readable and maintainable. Use this knowledge in
your projects and interviews to stand out! 🚀
🎯Async/Await
Explanation with Colorful Emoji and Highlights: Understanding
vs Traditional Promises

🧵 Key Highlights:
1️⃣ Promises Without Async/Await

🌟 Set Timeout in Promises: We introduce a setTimeout to simulate delays in


resolving promises.

const promise = new Promise((resolve) => {


setTimeout(() => resolve("Resolved Value"), 10000); //

JAVA SCRIPT 47
10-second delay
});

💡 Execution Flow:
Execution of synchronous code happens first.

The Promise's resolution happens asynchronously, after 10 seconds.

console.log("Namaste JavaScript");
promise.then((value) => console.log(value));

🖥️ Output:
Namaste JavaScript
(After 10 seconds) Resolved Value

💭 Why? JavaScript doesn’t wait; it registers the callback and moves to


the next line.

2️⃣ Promises with Async/Await

🌈 Using await Inside an async Function:

async function handlePromise() {


console.log("Namaste JavaScript");
const result = await promise;
console.log(result);
}
handlePromise();

🔍 Execution Flow:
Synchronous code is executed up to await .

At await , the function suspends until the Promise resolves.

🖥️ Output:
(After 10 seconds) Namaste JavaScript
Resolved Value

JAVA SCRIPT 48
Key Difference: In this case, JavaScript appears to wait before
proceeding to the next line, but only within the async function.

3️⃣ Visualizing the Call Stack


Call Stack Operations:

🟩 : Executes and clears the stack.


console.log("Namaste JavaScript")

🟦 : Suspends function execution (temporarily removed from


await promise

the stack).

🟨 Resolved promise: Re-adds suspended function to the stack and


continues execution.

Behavior With Multiple Promises:

async function multiPromise() {


const val1 = await promise1; // Resolves in 5 seconds
const val2 = await promise2; // Resolves in 10 seconds
console.log(val1, val2);
}

Execution waits for each await , resolving them sequentially.

Parallel Execution: Achievable with Promise.all .

4️⃣ Complex Cases and Behavior


Two Promises with Different Timers:

const promise1 = new Promise((resolve) => setTimeout(() =>


resolve("P1 Resolved"), 5000));
const promise2 = new Promise((resolve) => setTimeout(() =>
resolve("P2 Resolved"), 10000));
async function demo() {
console.log("Starting...");
const val1 = await promise1;
console.log(val1);
const val2 = await promise2;
console.log(val2);
}

🖥️ Output:

JAVA SCRIPT 49
Starting...
(After 5 seconds) P1 Resolved
(After 10 seconds) P2 Resolved

With Reversed Order of Resolution: Execution adapts to the promise order


defined by await .

5️⃣ Behind the Scenes


What Happens at await ?

The current function execution suspends.

The JavaScript engine is not blocked. Other events or processes can run.

Key Learning: JavaScript never blocks the call stack; it merely suspends
specific function execution temporarily.

6️⃣ Advanced Example: Parallel Execution with Promise.all

async function parallelDemo() {


const [val1, val2] = await Promise.all([promise1, promise
2]);
console.log(val1, val2);
}

🌟 Result: Both promises resolve simultaneously; logs appear together after 10


seconds.

🌟 Takeaway Notes:
✅ Async/Await simplifies promise management and introduces sequential
behavior.

✅ JavaScript appears to wait at , but it’s an illusion; it suspends the


await

function while keeping the engine free.

✅ Use Promise.allfor parallel execution.

🚀 Debugging Tip: Use breakpoints in developer tools to see how the call
stack evolves during promise resolution.

🎉 Enjoy a smoother journey with async/await!

JAVA SCRIPT 50
Here's a detailed, structured, and color-coded explanation of the remaining script
from the YouTube video. It will break down the points, provide code snippets, and
summarize concepts effectively.

🚀 Detailed Notes with Code and Explanation


🔵 1. Concept of and Behind the Scenes
async await
🌟 Importance of Understanding :
💬
async/await

"Behind the scenes of async/await might seem confusing, but once


understood, it simplifies asynchronous programming immensely."
📌 Points to Remember:

JavaScript is non-blocking and uses an event loop.

async/await suspends function execution but does not block JavaScript


entirely.

🔴 2. Reverse Example with Promises


🕒 Example: P1 (10 seconds), P2 (5 seconds)
🔑 Explanation:
Hello World is logged immediately.

P1 (10 seconds): Execution suspends until resolved.

Only after P1 is resolved, execution moves to P2 (already resolved).

Result:

After 10 seconds: Logs result of P1 .

Immediately after: Logs result of P2 .

🟢 3. JavaScript's Event Loop


💡 Key Insights:
JavaScript does not pause or block for await .

While waiting for promises to resolve:

The call stack remains free.

Other operations (e.g., user clicks) continue without issues.

JAVA SCRIPT 51
🔵 4. Debugging with Examples
📋 Example Setup: P1 (20 seconds), P2 (40 seconds):
Call stack becomes empty after initiating await .

Execution resumes once promises resolve.

Logs occur sequentially:

After 20 seconds: Logs P1 .

After 40 seconds: Logs P2 .

🌈 Code Example: Fetch API with async/await

const API_URL = "https://api.github.com/users/AkshayMark7th";

async function handlePromise() {

🟢
try {
const response = await fetch(API_URL); // Fetch API ca

🔵
ll
const data = await response.json(); // Convert resp

🔴
onse to JSON
console.log(data); // Log JSON res
ult


} catch (error) {
console.error("Error fetching data:", error); // Handl
e errors
}
}

handlePromise();

🔴 Error Handling Techniques


🔑 Method 1: Try-Catch Block
Use try for code and catch for error handling.

async function fetchData() {


try {
const response = await fetch(API_URL);

JAVA SCRIPT 52
const data = await response.json();
console.log(data);
} catch (error) {
console.error("An error occurred:", error);
}
}

🔵 Method 2: .catch for Promises

Handle errors with .catch() .

handlePromise().catch((error) => {
console.error("Error caught:", error);
});

🎨 Color-Coded Points Summary


🟢 Key Takeaways:
1. JavaScript’s event loop ensures non-blocking execution.

2. async/await suspends function execution without halting other tasks.

3. Fetch API returns a promise that can be handled using await or .then .

🔴 Practical Advice:
Use try-catch for better readability and cleaner error handling.

Debug with call stack tools to understand promise resolution timing.

🌟 Motivation to Learn:
These concepts are critical for JS interviews and professional development.

🔥 Share & Spread Knowledge: Support content creators by liking, sharing,


and commenting!

Let me know if you'd like a continuation, examples, or anything adjusted!

JAVA SCRIPT 53
JAVA SCRIPT 54

You might also like