---
source_hash: "4d2384dd"
title: "Chapter 3: Asynchronous Programming"
weight: 330
---

# Chapter 3: Asynchronous Programming

## Introduction

In JavaScript, many operations are **asynchronous**:

- API calls (fetch)
- File reading
- Timers (setTimeout)
- Local database access (IndexedDB)

Unlike PHP where code executes line by line, JavaScript can start an operation and continue without waiting for the result.

## The Problem

```javascript
// This code doesn't do what you think!
console.log("1. Start");

setTimeout(() => {
    console.log("2. Inside timeout");
}, 1000);

console.log("3. End");

// Output:
// "1. Start"
// "3. End"
// "2. Inside timeout" (1 second later)
```

## Promises

A Promise represents a value that will be available in the future.

### Promise States

- **pending**: waiting
- **fulfilled**: successfully resolved (contains a value)
- **rejected**: rejected (contains an error)

### Creating a Promise

```javascript
const myPromise = new Promise((resolve, reject) => {
    // Simulated asynchronous operation
    setTimeout(() => {
        const success = true;

        if (success) {
            resolve("Data received"); // Success
        } else {
            reject(new Error("Failure")); // Error
        }
    }, 1000);
});
```

### Consuming a Promise with .then() and .catch()

```javascript
myPromise
    .then(result => {
        console.log("Success:", result);
    })
    .catch(error => {
        console.log("Error:", error.message);
    });

// Chaining .then()
fetchUser(1)
    .then(user => fetchPosts(user.id))
    .then(posts => console.log(posts))
    .catch(error => console.log("Error:", error));
```

## async/await

`async/await` is a more readable syntax for working with Promises.

### Basic Syntax

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

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

### Important Rules

1. `await` can only be used inside an `async` function
2. An `async` function always returns a Promise
3. `await` "pauses" execution until the Promise is resolved

### Comparative Example

```javascript
// With .then()
function getUserPosts(userId) {
    return fetchUser(userId)
        .then(user => fetchPosts(user.id))
        .then(posts => {
            console.log(posts);
            return posts;
        });
}

// With async/await (more readable)
async function getUserPosts(userId) {
    const user = await fetchUser(userId);
    const posts = await fetchPosts(user.id);
    console.log(posts);
    return posts;
}
```

## Error Handling

### With try/catch

```javascript
async function fetchData() {
    try {
        const response = await fetch("https://api.example.com/data");

        if (!response.ok) {
            throw new Error(`HTTP ${response.status}`);
        }

        const data = await response.json();
        return data;

    } catch (error) {
        console.error("Error:", error.message);
        // Handle error (display message, return default value, etc.)
        return null;
    }
}
```

### Common Pattern in React

```javascript
const [data, setData] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);

const loadData = async () => {
    setLoading(true);
    setError(null);

    try {
        const response = await fetch("/api/items");
        const result = await response.json();
        setData(result);
    } catch (err) {
        setError(err.message);
    } finally {
        setLoading(false);
    }
};
```

## Sequential vs Parallel Execution

### Sequential (one after another)

```javascript
async function sequential() {
    const user = await fetchUser(1);      // Wait...
    const posts = await fetchPosts(1);    // Then wait...
    const comments = await fetchComments(1); // Then wait...

    // Total time = time1 + time2 + time3
}
```

### Parallel (at the same time)

```javascript
async function parallel() {
    // Start all 3 requests at the same time
    const [user, posts, comments] = await Promise.all([
        fetchUser(1),
        fetchPosts(1),
        fetchComments(1)
    ]);

    // Total time = max(time1, time2, time3)
}
```

### Promise.all vs Promise.allSettled

```javascript
// Promise.all - fails if ONE promise fails
try {
    const results = await Promise.all([promise1, promise2, promise3]);
} catch (error) {
    // One of the promises failed
}

// Promise.allSettled - waits for all, even if some fail
const results = await Promise.allSettled([promise1, promise2, promise3]);
// results = [
//   { status: "fulfilled", value: ... },
//   { status: "rejected", reason: Error },
//   { status: "fulfilled", value: ... }
// ]
```

## Comparison with PHP

```php
// PHP - synchronous by default
$user = file_get_contents("https://api.example.com/user/1");
$posts = file_get_contents("https://api.example.com/posts/1");
// Each line waits for the previous one to finish
```

```javascript
// JavaScript - asynchronous
const user = await fetch("https://api.example.com/user/1");
const posts = await fetch("https://api.example.com/posts/1");
// Similar thanks to await, but under the hood it's asynchronous
```

## Common Pitfalls

### 1. Forgetting await

```javascript
// INCORRECT
async function getData() {
    const data = fetch("/api/data"); // Forgot await!
    console.log(data); // Promise { <pending> } - not the data!
}

// CORRECT
async function getData() {
    const response = await fetch("/api/data");
    const data = await response.json();
    console.log(data);
}
```

### 2. await in a loop (unintended sequential)

```javascript
// SLOW - each iteration waits for the previous one
async function slow() {
    for (const id of ids) {
        const data = await fetchItem(id); // Sequential!
    }
}

// FAST - all requests in parallel
async function fast() {
    const promises = ids.map(id => fetchItem(id));
    const results = await Promise.all(promises);
}
```

### 3. Not handling errors

```javascript
// DANGEROUS - unhandled error
async function riskyCode() {
    const data = await fetchData(); // What if it fails?
}

// SAFE - error handled
async function safeCode() {
    try {
        const data = await fetchData();
    } catch (error) {
        console.error("Handled error:", error);
    }
}
```

## Exercises

### Exercise 1: Convert to async/await

Convert this code using `.then()`:

```javascript
function getUser(id) {
    return fetch(`/api/users/${id}`)
        .then(response => response.json())
        .then(user => {
            console.log(user);
            return user;
        })
        .catch(error => {
            console.error("Error:", error);
            return null;
        });
}
```

**Solution:**

```javascript
async function getUser(id) {
    try {
        const response = await fetch(`/api/users/${id}`);
        const user = await response.json();
        console.log(user);
        return user;
    } catch (error) {
        console.error("Error:", error);
        return null;
    }
}
```

### Exercise 2: Parallelization

Optimize this code to execute requests in parallel:

```javascript
async function loadDashboard(userId) {
    const user = await fetchUser(userId);
    const orders = await fetchOrders(userId);
    const notifications = await fetchNotifications(userId);

    return { user, orders, notifications };
}
```

**Solution:**

```javascript
async function loadDashboard(userId) {
    const [user, orders, notifications] = await Promise.all([
        fetchUser(userId),
        fetchOrders(userId),
        fetchNotifications(userId)
    ]);

    return { user, orders, notifications };
}
```

## Key Points to Remember

1. **Promise**: represents a future value (pending -> fulfilled/rejected)
2. **async/await**: readable syntax for Promises
3. **await**: "pauses" execution until resolution
4. **try/catch**: error handling with async/await
5. **Promise.all**: execute multiple Promises in parallel
6. **Always handle errors** with try/catch

[<- Previous Chapter](/training/module1-javascript-es6/fonctions) | [Back to Module](/training/module1-javascript-es6) | [Next Chapter: ES6 Modules ->](/training/module1-javascript-es6/modules-es6)
