USD ($)
$
United States Dollar
Euro Member Countries
India Rupee

Modules , Promises/Async-Await, Fetch API for AJAX

Lesson 22/30 | Study Time: 28 Min

Modern JavaScript provides powerful features to build well-structured and responsive web applications.

Modules allow developers to organize code into reusable files using import and export, improving readability and maintainability.

Promises and async–await simplify handling asynchronous operations, making code easier to understand and manage without deeply nested callbacks.

The Fetch API enables asynchronous communication with servers, allowing applications to send and receive data dynamically without reloading the page.

ES6 Modules: import/export

Modules let you split code into reusable files, eliminating global scope pollution and enabling tree-shaking for smaller bundles.

Introduced in ES6 and now supported by all browsers, they follow the same import/export syntax across frontend and backend.

Declaring and Exporting Modules

Exports make functions, classes, or variables available to other files. Use named exports for multiple items or default exports for single primary exports.


Export Patterns:



Complete example (math.js)

javascript
// Named exports
export const PI = 3.14159;
export function circleArea(radius) {
return PI * radius * radius;
}

// Default export
export default function squareArea(side) {
return side * side;
}


Importing Modules

Imports reference exported items by exact name (named) or any name (default). Use relative paths like ./math.js (same folder) or ../utils.js (parent folder).


Import syntax


1. Named: import { PI, circleArea } from './math.js';

2. Default: import area from './math.js';

3. Alias: import { PI as piValue } from './math.js';

4. Multiple: import squareArea, { PI } from './math.js';


Browser usage (add to HTML)

xml
<script type="module" src="app.js"></script>



Pro Tip: Always use modules in production—your code becomes importable by frameworks automatically.

Promises: Handling Asynchronous Code

Promises represent eventual completion (or failure) of async operations like API calls or timers.

They chain .then() for success and .catch() for errors, avoiding callback hell.

Promise Lifecycle and Chaining

A promise starts as pending, becomes fulfilled (resolved) or rejected. Chain multiple operations without nesting.


Basic lifecycle

javascript
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => resolve("Success!"), 1000);
});

myPromise
.then(result => console.log(result))
.catch(error => console.error(error));


Real example - Fetch user data


Create promise with fetch()

.then() parse JSON

.then() display data

.catch() handle network errors


Chaining multiple promises

javascript
fetchUser()
.then(user => fetchPosts(user.id))
.then(posts => displayPosts(posts))
.catch(handleError);

Common Promise Methods

Master these static methods for complex flows


Promise.all() practical

javascript
Promise.all([fetchUsers(), fetchPosts()])
.then(([users, posts]) => renderDashboard(users, posts));

Async/Await: Cleaner Promise Syntax

Async/await is syntactic sugar over promises, making asynchronous code read like synchronous. Use async functions and await keyword for cleaner error handling with try/catch.


Writing Async Functions

Mark functions async—they always return promises. await pauses execution until promise settles.


Basic conversion

javascript
// Promise chaining
fetch('/api/user').then(r => r.json()).then(display);

// Async/await equivalent
async function getUser() {
const response = await fetch('/api/user');
const user = await response.json();
display(user);
}


Error handling

javascript
async function safeFetch() {
try {
const data = await fetchData();
return data;
} catch (error) {
console.error('Fetch failed:', error);
return null;
}
}


Parallel vs Sequential Awaits

Avoid sequential blocking—use Promise.all():

Pattern                           Speed                   Use Case
await p1; await p2;SequentialDependencies
await Promise.all([p1, p2]);ParallelIndependent


Dashboard example

javascript
async function loadDashboard() {
const [users, posts, stats] = await Promise.all([
fetch('/api/users'),
fetch('/api/posts'),
fetch('/api/stats')
]);
renderAll(users.json(), posts.json(), stats.json());
}

Fetch API: Modern AJAX

Fetch API replaces XMLHttpRequest with a promise-based interface for HTTP requests. Native to browsers since 2015, it supports modern features like streaming and CORS.

Making Basic Requests

Fetch returns a Response object—always check ok status and parse JSON manually.


GET request

javascript
async function fetchUsers() {
try {
const response = await fetch('https://api.github.com/users');
if (!response.ok) throw new Error('Network error');
return await response.json();
} catch (error) {
console.error(error);
}
}


POST request with JSON:

javascript
async function createUser(userData) {
const response = await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(userData)
});
return response.json();
}


Advanced Fetch Features

Handle real-world scenarios:



Complete example with Abort

javascript
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 5000);

fetch('/api/slow', { signal: controller.signal })
.then(r => r.json())
.catch(err => {
if (err.name === 'AbortError') console.log('Request timeout');
});