0% found this document useful (0 votes)
22 views16 pages

Advanced JavaScript: Async Programming Guide

The document provides an in-depth overview of advanced JavaScript concepts, focusing on asynchronous programming, error handling, and modular coding practices. It covers essential topics such as callbacks, promises, async/await syntax, the Fetch API, JSON handling, and working with external APIs. Additionally, it emphasizes best practices for writing maintainable and efficient code, making it a valuable resource for developers looking to enhance their JavaScript skills.

Uploaded by

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

Advanced JavaScript: Async Programming Guide

The document provides an in-depth overview of advanced JavaScript concepts, focusing on asynchronous programming, error handling, and modular coding practices. It covers essential topics such as callbacks, promises, async/await syntax, the Fetch API, JSON handling, and working with external APIs. Additionally, it emphasizes best practices for writing maintainable and efficient code, making it a valuable resource for developers looking to enhance their JavaScript skills.

Uploaded by

unluvkyguy.21
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Table of Contents

Introduction..........................................................4
Synchronous vs asynchronous programming.........................4
What it means.......................................................................... 4
 Synchronous.................................................................................4
 Asynchronous...............................................................................4
Why JS cares........................................................................... 4
How it works (high level)............................................................4
Quick demo (order matters).........................................................5
When to use which.................................................................... 5

Callbacks & callback hell.............................................5


Callback basics.........................................................................5
Callback hell (aka pyramid of doom)..............................................5
Problems:...........................................................................................6
Workarounds.......................................................................................6

Promises: resolve, reject, chaining....................................6


Concepts.................................................................................6
Basic example......................................................................................6
Chaining.................................................................................7
Useful static helpers...................................................................7
Error propagation......................................................................7

Async/await syntax...................................................7
Syntactic sugar.........................................................................7
Example.............................................................................................8
Key points...........................................................................................8
When not to use....................................................................................8

Fetch API for HTTP requests.........................................9


Basics.................................................................................... 9

1
GET example.......................................................................................9
POST JSON example (async/await)...........................................................9
Important gotchas.................................................................................9
Advanced............................................................................................9

JSON handling in JavaScript.......................................10


Serializing.............................................................................10
Parsing.................................................................................10
Pitfalls................................................................................. 10
Example...........................................................................................10

Error handling in async code........................................11


Patterns................................................................................ 11
Graceful handling....................................................................11
Uncaught rejections.................................................................11
Example helper (fetch with error wrapper)................................................11
Retries + backoff....................................................................11

ES modules: import, export, default export.........................12


Syntax..................................................................................12
Re-exporting..........................................................................12
Dynamic import......................................................................12
Notes................................................................................... 12
Best practice..........................................................................13

Modularizing JavaScript code......................................13


Goals................................................................................... 13
Structure example...................................................................13
Patterns................................................................................ 13
Bundlers vs native modules.......................................................13
Encapsulation.........................................................................14

Working with external APIs........................................14

2
Steps before coding.................................................................14
Authentication........................................................................14
CORS.................................................................................. 14
Pagination.............................................................................14

Rate limiting........................................................14
Example: authenticated paginated fetch + retry...............................15
Security best practices..............................................................15
Testing.................................................................................15

Quick best-practices & checklist....................................16

3
MODULE 7: Advanced JavaScript
Introduction
Advanced JavaScript goes beyond the basics of variables, loops, and functions, diving into
the powerful features that make JavaScript one of the most versatile programming languages.
It covers concepts like asynchronous programming with callbacks, promises, and
async/await, which allow developers to handle real-time operations such as API calls and
event-driven tasks. Advanced topics also include closures, prototypes, the event loop, and
execution context, which give developers deep insight into how JavaScript works under the
hood. Modern features such as ES6+ modules, destructuring, spread/rest operators, arrow
functions, and classes improve code readability and maintainability. Additionally, advanced
JavaScript emphasizes modular coding practices, DOM manipulation for dynamic user
interfaces, error handling, and working with external APIs to build interactive and scalable
web applications. Mastering these concepts equips developers with the skills to write cleaner,
more efficient, and production-ready code.

Synchronous vs asynchronous programming


What it means
 Synchronous code runs top-to-bottom and blocks subsequent steps until the current
operation completes. Example: heavy computation or a blocking IO call would
prevent anything else from running.

 Asynchronous code schedules work to happen later (non-blocking). The engine


continues executing the next lines while the async work proceeds in the background
(I/O, timers, network).

Why JS cares
 JavaScript in the browser is single-threaded (UI thread + event loop). If you run long
synchronous code, the UI freezes. Asynchrony keeps UI responsive.

How it works (high level)


 The event loop coordinates:

o The call stack runs current functions.

o Web APIs / timers / network do work in background.

o Completed async work queues callbacks to the task queues.

4
o Microtask queue (promises) runs between macrotasks (setTimeout, events).

 Important: Promises (then/catch) callbacks run as microtasks, which execute before


the next macrotask.

Quick demo (order matters)


[Link]('start');

setTimeout(() => [Link]('timeout 0'), 0);

[Link]().then(() => [Link]('promise'));

[Link]('end');

// Output:
// start
// end
// promise
// timeout 0

Explanation: promise is a microtask and runs before setTimeout (a macrotask).

When to use which


 Synchronous for quick, deterministic logic.

 Asynchronous for I/O, network requests, timers, large computations (or offload to
Web Worker).

Callbacks & callback hell


Callback basics
A callback is a function passed as an argument and executed later:

function doWork(cb) {
setTimeout(() => { cb(null, 'done'); }, 500);
}
doWork((err, result) => {
if (err) [Link](err);
else [Link](result);
});

5
Callback hell (aka pyramid of doom)
Nested callbacks for sequential async tasks quickly become unreadable:

login(user, pass, (err, userInfo) => {


if (err) return handle(err);
fetchProfile([Link], (err, profile) => {
if (err) return handle(err);
fetchPermissions(profile, (err, perms) => {
if (err) return handle(err);
// ...deep nesting
});
});
});

Problems:
 Hard to read & maintain

 Error handling duplication

 Hard to compose tasks or run them in parallel

 Stack traces get confusing

Workarounds
 Use named functions instead of anonymous nested ones (improves readability).

 Convert callback-based APIs to Promises (promisify) and use Promise chaining or


async/await.

Promises: resolve, reject, chaining


Concepts
 A Promise represents a value that may be available now, later, or never.

 States: pending → fulfilled (resolved) OR rejected.

 The executor new Promise((resolve, reject) => { ... }) runs immediately.

Basic example
const p = new Promise((resolve, reject) => {
setTimeout(() => {
if ([Link]() > 0.2) resolve('ok');
else reject(new Error('failed'));

6
}, 300);
});

[Link](value => {
[Link]('success', value);
}).catch(err => {
[Link]('error', err);
}).finally(() => {
[Link]('done');
});

Chaining
 Each .then() returns a new Promise. Returning a value continues the chain; returning a
Promise waits for it.

fetch('/api/user') // returns Promise<Response>


.then(res => [Link]()) // returns Promise<object>
.then(user => fetch(`/api/${[Link]}/orders`))
.then(res => [Link]())
.then(orders => [Link](orders))
.catch(err => [Link]('any error from above', err));

Useful static helpers


 [Link]([p1,p2]) — resolves when all resolve, rejects if any reject.

 [Link]([p1,p2]) — wait for all, get results even if some fail.

 [Link]([p1,p2]) — resolves/rejects as soon as first settles.

 [Link]([p1,p2]) — resolves with first fulfilled, rejects if all reject.

Error propagation
 Throwing inside .then() causes rejection for the next .catch().

 Avoid mixing callback-style error handling with Promise rejection; prefer .catch().

Async/await syntax
Syntactic sugar
 async function implicitly returns a Promise.

7
 await pauses execution inside the async function until the awaited Promise resolves
(non-blocking the whole thread — other tasks still run).

Example
async function loadUserAndOrders() {
try {
const resUser = await fetch('/api/user');
if (![Link]) throw new Error('User fetch failed');
const user = await [Link]();

// parallel: start both requests before awaiting


const ordersPromise = fetch(`/api/${[Link]}/orders`);
const messagesPromise = fetch(`/api/${[Link]}/messages`);

const [ordersRes, messagesRes] = await [Link]([ordersPromise, messagesPromise]);


const orders = await [Link]();
const messages = await [Link]();

return { user, orders, messages };


} catch (err) {
// handle or rethrow
[Link]('error', err);
throw err;
}
}

Key points
 await only works inside async functions (note: modern modules support top-level
await).

 Use [Link] for parallelism. Avoid await inside loops if you want concurrency:

// bad — sequential
for (const id of ids) {
await doFetch(id);
}
// good — parallel
await [Link]([Link](id => doFetch(id)));

When not to use


 For fire-and-forget tasks where you don't need to await completion (but ensure errors
are handled).

8
Fetch API for HTTP requests
Basics
 fetch(url, options) returns a Promise that resolves to a Response.

 [Link] indicates 2xx status. [Link]() returns a Promise for parsed JSON.

GET example
fetch('/api/data')
.then(res => {
if (![Link]) throw new Error(`HTTP ${[Link]}`);
return [Link]();
})
.then(data => [Link](data))
.catch(err => [Link]('network or parse error', err));

POST JSON example (async/await)


async function postData(url, payload) {
const res = await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: [Link](payload),
});
if (![Link]) throw new Error(`HTTP ${[Link]}`);
return [Link]();
}

Important gotchas
 fetch rejects only on network errors; HTTP 4xx/5xx do NOT reject. Always check
[Link].

 To abort requests, use AbortController:

const controller = new AbortController();


fetch('/api', { signal: [Link] });
// [Link]() to cancel

 Handle timeouts by combining AbortController with setTimeout.

9
Advanced
 fetch can stream responses via [Link]() (useful for large responses).

 Use mode, credentials, cache, etc. in options when needed.

JSON handling in JavaScript


Serializing
 [Link](value[, replacer, space])

o space is indentation (e.g., 2).

o Functions, undefined, and symbols are omitted (or converted in arrays to null).

o Circular references throw TypeError.

Parsing
 [Link](text[, reviver])

o reviver lets you convert strings to Dates or other types:

const obj = [Link](text, (k, v) => {


if (typeof v === 'string' && /^\d{4}-\d{2}-\d{2}T/.test(v)) return new Date(v);
return v;
});

Pitfalls
 Date becomes string in JSON; reconstruct manually.

 Big integers beyond Number.MAX_SAFE_INTEGER lose precision (use strings or


BigInt + custom serialization).

 Always try/catch around [Link] for malformed input.

Example
try {
const obj = [Link](userInput);
} catch (err) {
[Link]('Invalid JSON', err);
}

10
Error handling in async code
Patterns
 Promises: use .catch() at the end of chains.

 async/await: wrap await calls in try/catch.

 Always rethrow if you can't handle the error at the current level.

Graceful handling
 Normalize errors so upper layers can display consistent messages (create custom
ApiError with status/res).

 For UI, show friendly messages and fallback UI.

Uncaught rejections
 Unhandled Promise rejections may be logged/warned and can terminate Node
processes in future—always attach .catch() or try/catch.

Example helper (fetch with error wrapper)


class ApiError extends Error {
constructor(message, response) { super(message); [Link] = response; }
}

async function safeFetch(url, opts) {


const res = await fetch(url, opts);
const text = await [Link](); // read body
let data;
try { data = text ? [Link](text) : null; } catch (err) { data = text; }
if (![Link]) throw new ApiError(`HTTP ${[Link]}`, { status: [Link], body: data });
return data;
}

Retries + backoff
 For transient network errors, implement retries with exponential backoff + jitter.

 Avoid retrying on client errors (4xx) unless specific (e.g., rate-limited 429 often needs
wait).

11
ES modules: import, export, default export
Syntax
 Named export:

// [Link]
export function add(a,b){ return a+b; }
export const PI = 3.14;

// [Link]
import { add, PI } from './[Link]';

 Default export:

// [Link]
export default function greet(name){ return `Hi ${name}`; }

// [Link]
import greet from './[Link]';

 You can mix:

export default class A {}


export const x = 1;

Re-exporting
export * from './[Link]';
export { special } from './[Link]';

Dynamic import
 Load modules lazily:

[Link]('click', async () => {


const module = await import('./[Link]');
[Link]();
});

Notes
 In browsers, use <script type="module"> or serve as modules.

 File extensions (.js) are usually required for native browser imports.

12
 Top-level await is allowed in modules (modern browsers & Node with ESM).

Best practice
 Prefer named exports for clarity and better tooling / tree-shaking.

 Use default export when module only exposes one primary thing.

Modularizing JavaScript code


Goals
 Single responsibility per module

 Small, testable units

 Clear public API (export surface)

 No global variables

Structure example
/src
/api
[Link] // re-exports api functions
[Link]
[Link]
/ui
[Link]
[Link]
[Link]
[Link] // app bootstrap

Patterns
 Use an [Link] in folders to re-export useful functions: export * from './[Link]';
export * from './[Link]'.

 Keep side-effects out of modules (pure functions easier to test). If module must run
side-effects, explicitly provide init().

Bundlers vs native modules


 For broad browser compatibility or advanced features (assets, transpilation), use
bundlers (Webpack, Rollup, Vite). For modern browsers, native ESM is fine.

13
Encapsulation
 Hide internals: export only what’s needed. Internal helpers stay non-exported.

Working with external APIs


Steps before coding
1. Read API docs (endpoints, params, auth method, rate limits).

2. Get a test key / sandbox environment.

3. Test endpoints with Postman or cURL.

Authentication
 Common types: API key, Bearer token (OAuth2), Basic auth.

 Never store secret keys in client-side code — use a server to keep secrets and proxy
requests if necessary.

CORS
 Browsers require the server to allow cross-origin requests (CORS headers). If you hit
a CORS error, the API or a proxy must be configured.

Pagination
 APIs return paginated results (page/cursor). Example pattern using page:

async function fetchAllPages(url) {


let page = 1, all = [];
while (true) {
const res = await fetch(`${url}?page=${page}`);
const { items, nextPage } = await [Link]();
[Link](...items);
if (!nextPage) break;
page = nextPage;
}
return all;
}

Rate limiting
 Respect Retry-After and 429 responses. Implement exponential backoff and caching
where reasonable.

14
Example: authenticated paginated fetch + retry
async function apiGet(url, token, maxRetries = 3) {
let attempt = 0;
while (attempt <= maxRetries) {
try {
const res = await fetch(url, {
headers: {
Authorization: `Bearer ${token}`,
Accept: 'application/json'
}
});
if ([Link] === 429) {
const wait = [Link]('Retry-After') || (2 ** attempt) * 1000;
await new Promise(r => setTimeout(r, wait));
attempt++;
continue;
}
if (![Link]) throw new Error(`HTTP ${[Link]}`);
return await [Link]();
} catch (err) {
if (attempt === maxRetries) throw err;
attempt++;
await new Promise(r => setTimeout(r, 2 ** attempt * 200));
}
}
}

Security best practices


 Keep tokens out of client-side source; forward requests through a backend when
secrets are required.

 Use HTTPS.

 Validate and sanitize data received from external APIs.

Testing
 Mock API responses for unit tests (tools: msw, sinon, jest mocks).

 Use integration tests in a sandbox environment.

15
Quick best-practices & checklist
 Prefer async/await for readability but use [Link] for parallel tasks.

 Always check HTTP response status with fetch (don’t rely on rejection).

 Normalize and centralize API error handling (ApiClient layer).

 Use AbortController to cancel long-running requests.

 Keep modules small and export explicit named APIs.

 Do not store secrets in client code; proxy via server for sensitive requests.

 Handle JSON parsing errors and validate incoming data.

 Implement exponential backoff + jitter for retries.

 Monitor unhandled promise rejections in development (attach .catch())

16

You might also like