[Go to site: main page, start]

0% found this document useful (0 votes)
2 views9 pages

Advanced JS Part3 Async JavaScript

This document is a practical guide on advanced JavaScript, focusing on asynchronous programming techniques such as Promises, the Fetch API, and async/await. It covers key concepts, best practices, and examples for handling asynchronous operations, including AJAX and various Promise methods like Promise.all() and Promise.race(). The guide aims to equip developers with the knowledge to effectively manage asynchronous code in JavaScript.

Uploaded by

rajjasra1970
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)
2 views9 pages

Advanced JS Part3 Async JavaScript

This document is a practical guide on advanced JavaScript, focusing on asynchronous programming techniques such as Promises, the Fetch API, and async/await. It covers key concepts, best practices, and examples for handling asynchronous operations, including AJAX and various Promise methods like Promise.all() and Promise.race(). The guide aims to equip developers with the knowledge to effectively manage asynchronous code in JavaScript.

Uploaded by

rajjasra1970
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

Advanced JavaScript

Asynchronous JavaScript
A Practical Guide

2026

Chapter 12: Promises


Creating a promise
Chaining
Promise states are final
Best practices
Chapter 13: [Link]() and Friends
[Link]()
[Link]()
[Link]()
[Link]()
Best practices
Chapter 14: AJAX ( XMLHttpRequest )
A basic GET request
A POST request with a JSON body
Tracking upload progress (something fetch can’t do natively)
Why fetch mostly replaced XHR
Best practices
Chapter 15: The Fetch API
Basic GET request
POST with JSON
Common request options
Aborting a request
Reading different response types
Best practices
Chapter 16: Async and Await
The basics
Error handling with try/catch
Sequential vs. concurrent awaits (a common performance mistake)
async with array methods (a common trap)
Top-level await
Best practices
Part 3 Summary
Chapter 12: Promises
A Promise represents a value that may not be available yet — the result of an asynchronous operation. It’s always in one of
three states: pending, fulfilled, or rejected.

Creating a promise

function wait(ms) {
return new Promise((resolve, reject) => {
if (ms < 0) {
reject(new Error("Duration cannot be negative"));
return;
}
setTimeout(() => resolve(`Waited ${ms}ms`), ms);
});
}

wait(500)
.then(result => [Link](result)) // "Waited 500ms"
.catch(error => [Link](error));

Chaining

Each .then() returns a new promise, which is what allows chaining without “callback hell.”

fetchUser(1)
.then(user => fetchPosts([Link]))
.then(posts => [Link](p => [Link]))
.then(published => [Link](published))
.catch(err => [Link]("Something failed:", [Link]))
.finally(() => [Link]("Request finished"));

.finally() runs regardless of success or failure — ideal for cleanup like hiding a loading spinner.

Promise states are final

Once a promise settles (fulfilled or rejected), it cannot change state again, and any .then() / .catch() attached later still fires
with that same result.

const p = [Link](42);
[Link](v => [Link]("first:", v));
[Link](v => [Link]("second:", v)); // both fire independently with 42

Best practices

Always attach a .catch() (or use try/catch with async/await) — unhandled rejections crash Node processes and log
warnings in browsers.
Return values from .then() callbacks to keep the chain flowing; forgetting to return inside a .then() is a classic bug.
Chapter 13: [Link]() and Friends
When you have multiple independent async operations, running them one after another wastes time. [Link]() and its
relatives run them concurrently.

[Link]()

Waits for all promises to fulfill, or rejects immediately if any one rejects.

const p1 = fetch("/api/users").then(r => [Link]());


const p2 = fetch("/api/posts").then(r => [Link]());
const p3 = fetch("/api/comments").then(r => [Link]());

[Link]([p1, p2, p3])


.then(([users, posts, comments]) => {
[Link](users, posts, comments);
})
.catch(err => [Link]("At least one request failed:", err));

If p2 rejects, the whole [Link]() rejects immediately — even if p1 and p3 would have succeeded.

[Link]()

Waits for all promises to finish, regardless of outcome, and reports each result individually. Use this when partial failure is
acceptable.

const results = await [Link]([p1, p2, p3]);


[Link]((result, i) => {
if ([Link] === "fulfilled") {
[Link](`Request ${i} succeeded:`, [Link]);
} else {
[Link](`Request ${i} failed:`, [Link]);
}
});

[Link]()

Settles as soon as the first promise settles (fulfilled or rejected) — useful for timeouts.

function withTimeout(promise, ms) {


const timeout = new Promise((_, reject) =>
setTimeout(() => reject(new Error("Timed out")), ms)
);
return [Link]([promise, timeout]);
}

withTimeout(fetch("/api/slow"), 3000)
.then(res => [Link]("Got response in time"))
.catch(err => [Link]([Link])); // "Timed out" if too slow

[Link]()

Settles as soon as the first promise fulfills; only rejects if all promises reject.

[Link]([fetch("/mirror1"), fetch("/mirror2"), fetch("/mirror3")])


.then(res => [Link]("First successful mirror responded"))
.catch(err => [Link]("All mirrors failed"));

Best practices

Use [Link]() when every result is required and any failure should abort the whole operation.
Use [Link]() when you want to know the outcome of every task, even if some fail.
Use [Link]() for timeout patterns.
Use [Link]() when you just need the fastest successful result (e.g., redundant servers).
Chapter 14: AJAX ( XMLHttpRequest )
AJAX (Asynchronous JavaScript and XML) is the original technique for making HTTP requests without reloading the page.
XMLHttpRequest (XHR) is the underlying API — largely superseded by fetch() today, but still common in legacy code and
certain use cases like upload progress tracking.

A basic GET request

const xhr = new XMLHttpRequest();


[Link]("GET", "/api/users", true);

[Link] = function () {
if ([Link] >= 200 && [Link] < 300) {
const data = [Link]([Link]);
[Link](data);
} else {
[Link]("Request failed with status", [Link]);
}
};

[Link] = function () {
[Link]("Network error");
};

[Link]();

A POST request with a JSON body

const xhr = new XMLHttpRequest();


[Link]("POST", "/api/users");
[Link]("Content-Type", "application/json");

[Link] = () => [Link]("Response:", [Link]);

[Link]([Link]({ name: "Alice", age: 30 }));

Tracking upload progress (something fetch can’t do natively)

const xhr = new XMLHttpRequest();


[Link]("POST", "/api/upload");

[Link] = (event) => {


if ([Link]) {
const percent = ([Link] / [Link]) * 100;
[Link](`Upload progress: ${[Link](1)}%`);
}
};

[Link](formData);

Why fetch mostly replaced XHR

XHR uses callbacks and event handlers, is verbose, and has an awkward API (checking readyState , separate onload / onerror
handlers). fetch() (Chapter 15) is promise-based and much cleaner for standard requests.

Best practices

Prefer fetch() for new code.


Reach for XMLHttpRequest specifically when you need upload progress events, which fetch does not support natively
(though the newer ReadableStream -based approaches are closing this gap).
Chapter 15: The Fetch API
fetch() is the modern, promise-based way to make HTTP requests.

Basic GET request

fetch("/api/users")
.then(response => {
if (![Link]) throw new Error(`HTTP error: ${[Link]}`);
return [Link]();
})
.then(data => [Link](data))
.catch(err => [Link]("Fetch failed:", err));

Important gotcha: fetch() only rejects on network failure. A 404 or 500 response is still a “successful” fetch as far as the
promise is concerned — you must check [Link] yourself.

POST with JSON

async function createUser(user) {


const response = await fetch("/api/users", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: [Link](user)
});
if (![Link]) throw new Error(`Failed: ${[Link]}`);
return [Link]();
}

Common request options

fetch("/api/protected", {
method: "GET",
headers: {
"Authorization": "Bearer " + token,
"Accept": "application/json"
},
credentials: "include", // send cookies for cross-origin requests
cache: "no-store"
});

Aborting a request

const controller = new AbortController();


const timeoutId = setTimeout(() => [Link](), 5000);

fetch("/api/slow", { signal: [Link] })


.then(res => [Link]())
.catch(err => {
if ([Link] === "AbortError") [Link]("Request was aborted");
})
.finally(() => clearTimeout(timeoutId));

Reading different response types

const res = await fetch("/api/data");


// [Link]() -> parsed JSON
// [Link]() -> plain string
// [Link]() -> binary data (e.g., images/files)
// [Link]() -> form data

Best practices

Always check [Link] before parsing the body.


Use AbortController for cancellable requests (e.g., search-as-you-type, navigating away from a page).
Wrap fetch calls in a reusable helper function to avoid repeating error-handling logic.
Chapter 16: Async and Await
async / await is syntactic sugar over promises that lets asynchronous code read like synchronous code.

The basics

async function getUser(id) {


const response = await fetch(`/api/users/${id}`);
if (![Link]) throw new Error("User not found");
const user = await [Link]();
return user;
}

// An `async` function always returns a promise


getUser(1).then(user => [Link](user));

Error handling with try/catch

async function loadDashboard() {


try {
const user = await getUser(1);
const posts = await getPosts([Link]);
return { user, posts };
} catch (error) {
[Link]("Dashboard failed to load:", [Link]);
throw error; // re-throw if the caller needs to know too
}
}

Sequential vs. concurrent awaits (a common performance mistake)

// Sequential - SLOW: each await blocks the next line, ~600ms total
async function slow() {
const a = await fetchA(); // 200ms
const b = await fetchB(); // 200ms
const c = await fetchC(); // 200ms
return [a, b, c];
}

// Concurrent - FAST: all three start immediately, ~200ms total


async function fast() {
const [a, b, c] = await [Link]([fetchA(), fetchB(), fetchC()]);
return [a, b, c];
}

Only use sequential await when each call genuinely depends on the previous result.

async with array methods (a common trap)

// BUG: forEach does not wait for async callbacks


async function processAll(items) {
[Link](async (item) => {
await save(item); // fires, but processAll() doesn't wait for these!
});
[Link]("Done"); // logs BEFORE the saves actually finish
}

// FIX: use a for...of loop, or [Link] with map


async function processAllFixed(items) {
await [Link]([Link](item => save(item)));
[Link]("Done"); // now genuinely waits
}

Top-level await

In ES modules, await can be used outside of an async function at the top level of a module.
// inside a .mjs file or <script type="module">
const config = await fetch("/[Link]").then(r => [Link]());
[Link](config);

Best practices

Always wrap await calls in try/catch (or handle rejection at a higher level) — an unhandled rejected promise inside an
async function surfaces as an unhandled promise rejection.
Run independent async operations concurrently with [Link]() rather than awaiting them one by one.
Never use async callbacks with forEach — it silently swallows the async behavior.
Part 3 Summary

Feature Purpose

Promise Represents a future value from async work

[Link]() / allSettled() / race() / any() Coordinate multiple promises

XMLHttpRequest (AJAX) Legacy HTTP requests, still useful for upload progress

fetch() Modern, promise-based HTTP requests

async / await Synchronous-looking syntax for async code

Next: Part 4 — Advanced Language Features, covering Symbols, Iterators, Generators, Strict Mode, and Error Handling.

You might also like