> For the complete documentation index, see [llms.txt](https://triyono.gitbook.io/tutorial/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://triyono.gitbook.io/tutorial/java-script/bab-5-asynchronous-programming.md).

# Bab 5: Asynchronous Programming

## Bab 5: Asynchronous Programming

### 5.1 Pengenalan Asynchronous Programming

#### 5.1.1 Konsep Dasar

* Perbedaan Synchronous vs Asynchronous
* Single-threaded nature of JavaScript
* Call Stack dan Event Loop
* Blocking vs Non-blocking operations
* Use cases untuk asynchronous programming

#### 5.1.2 Event Loop Explained

```javascript
console.log('Start');

setTimeout(() => {
    console.log('Timeout 1');
}, 0);

Promise.resolve().then(() => {
    console.log('Promise 1');
});

console.log('End');

// Output:
// Start
// End
// Promise 1
// Timeout 1
```

### 5.2 Callback

#### 5.2.1 Basic Callbacks

```javascript
// Simple callback example
function fetchData(callback) {
    setTimeout(() => {
        const data = { id: 1, name: 'John' };
        callback(data);
    }, 1000);
}

fetchData((result) => {
    console.log(result);
});

// Error handling with callbacks
function fetchDataWithError(success, error) {
    setTimeout(() => {
        const random = Math.random();
        if (random > 0.5) {
            success({ id: 1, name: 'John' });
        } else {
            error(new Error('Failed to fetch data'));
        }
    }, 1000);
}
```

#### 5.2.2 Callback Hell

```javascript
// Example of callback hell
fetchUser(function(user) {
    fetchUserPosts(user.id, function(posts) {
        fetchPostComments(posts[0].id, function(comments) {
            fetchCommentAuthor(comments[0].id, function(author) {
                console.log(author);
            }, function(error) {
                console.error('Error:', error);
            });
        }, function(error) {
            console.error('Error:', error);
        });
    }, function(error) {
        console.error('Error:', error);
    });
}, function(error) {
    console.error('Error:', error);
});

// Solution using named functions
function handleAuthor(author) {
    console.log(author);
}

function handleComments(comments) {
    fetchCommentAuthor(comments[0].id, handleAuthor, handleError);
}

function handlePosts(posts) {
    fetchPostComments(posts[0].id, handleComments, handleError);
}

function handleUser(user) {
    fetchUserPosts(user.id, handlePosts, handleError);
}

function handleError(error) {
    console.error('Error:', error);
}

fetchUser(handleUser, handleError);
```

### 5.3 Promise

#### 5.3.1 Promise Basics

```javascript
// Creating a Promise
const myPromise = new Promise((resolve, reject) => {
    // Async operation
    setTimeout(() => {
        const random = Math.random();
        if (random > 0.5) {
            resolve('Success!');
        } else {
            reject(new Error('Failed!'));
        }
    }, 1000);
});

// Using a Promise
myPromise
    .then(result => console.log(result))
    .catch(error => console.error(error))
    .finally(() => console.log('Completed'));

// Chaining Promises
fetchUser()
    .then(user => fetchUserPosts(user.id))
    .then(posts => fetchPostComments(posts[0].id))
    .then(comments => fetchCommentAuthor(comments[0].id))
    .then(author => console.log(author))
    .catch(error => console.error('Error:', error));
```

#### 5.3.2 Promise Methods

```javascript
// Promise.all
const promises = [
    fetch('/api/users'),
    fetch('/api/posts'),
    fetch('/api/comments')
];

Promise.all(promises)
    .then(([users, posts, comments]) => {
        // All promises resolved
    })
    .catch(error => {
        // Any promise rejected
    });

// Promise.race
Promise.race([
    fetch('/api/fast'),
    fetch('/api/slow')
])
.then(result => {
    // First resolved promise
});

// Promise.allSettled
Promise.allSettled([
    Promise.resolve(1),
    Promise.reject('error'),
    Promise.resolve(3)
])
.then(results => {
    // All promises settled (resolved or rejected)
});

// Promise.any
Promise.any([
    Promise.reject('error'),
    Promise.resolve(1),
    Promise.resolve(2)
])
.then(result => {
    // First fulfilled promise
});
```

### 5.4 Async/Await

#### 5.4.1 Basic Syntax

```javascript
async function fetchUserData() {
    try {
        const user = await fetchUser();
        const posts = await fetchUserPosts(user.id);
        const comments = await fetchPostComments(posts[0].id);
        const author = await fetchCommentAuthor(comments[0].id);
        return author;
    } catch (error) {
        console.error('Error:', error);
    }
}

// Using async/await with Promise methods
async function fetchMultipleData() {
    try {
        const [users, posts, comments] = await Promise.all([
            fetch('/api/users'),
            fetch('/api/posts'),
            fetch('/api/comments')
        ]);
        return { users, posts, comments };
    } catch (error) {
        console.error('Error:', error);
    }
}
```

#### 5.4.2 Error Handling

```javascript
// Try-catch block
async function handleErrors() {
    try {
        const result = await riskyOperation();
        return result;
    } catch (error) {
        console.error('Error:', error);
        throw new Error('Failed to handle operation');
    } finally {
        console.log('Operation completed');
    }
}

// Multiple try-catch blocks
async function complexOperation() {
    try {
        const data = await fetchData();
        try {
            const processed = await processData(data);
            return processed;
        } catch (processingError) {
            console.error('Processing error:', processingError);
            return data; // Return raw data if processing fails
        }
    } catch (fetchError) {
        console.error('Fetch error:', fetchError);
        return null;
    }
}
```

### 5.5 Event Loop dan SetTimeout/SetInterval

#### 5.5.1 SetTimeout

```javascript
// Basic setTimeout
setTimeout(() => {
    console.log('Delayed message');
}, 1000);

// Clearing timeout
const timeoutId = setTimeout(() => {
    console.log('This will not run');
}, 1000);

clearTimeout(timeoutId);

// Nested timeouts
function nestedTimeout() {
    setTimeout(() => {
        console.log('First');
        setTimeout(() => {
            console.log('Second');
        }, 500);
    }, 1000);
}
```

#### 5.5.2 SetInterval

```javascript
// Basic setInterval
const intervalId = setInterval(() => {
    console.log('Repeating message');
}, 1000);

// Clearing interval
setTimeout(() => {
    clearInterval(intervalId);
}, 5000);

// Dynamic interval
let counter = 0;
const dynamicInterval = setInterval(() => {
    console.log(++counter);
    if (counter >= 5) {
        clearInterval(dynamicInterval);
    }
}, 1000);
```

### 5.6 Error Handling

#### 5.6.1 Global Error Handling

```javascript
// Unhandled Promise Rejection
window.addEventListener('unhandledrejection', event => {
    console.error('Unhandled promise rejection:', event.reason);
});

// Global error handler
window.onerror = function(message, source, lineno, colno, error) {
    console.error('Global error:', {
        message,
        source,
        lineno,
        colno,
        error
    });
    return true; // Prevents default error handling
};
```

### 5.7 Praktik dan Latihan

#### 5.7.1 Project: Data Fetching Service

```javascript
class DataService {
    async fetchData(url, options = {}) {
        try {
            const response = await fetch(url, options);
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            return await response.json();
        } catch (error) {
            console.error('Fetch error:', error);
            throw error;
        }
    }

    async fetchMultiple(urls) {
        try {
            const promises = urls.map(url => this.fetchData(url));
            return await Promise.all(promises);
        } catch (error) {
            console.error('Multiple fetch error:', error);
            throw error;
        }
    }
}
```

### 5.8 Best Practices

* Proper error handling
* Avoiding callback hell
* Using async/await when possible
* Managing multiple async operations
* Performance considerations

### 5.9 Ringkasan

* Asynchronous programming fundamentals
* Different approaches to async operations
* Error handling strategies
* Common patterns dan solutions

### 5.10 Latihan Akhir Bab

1. Create a data fetching library
2. Implement a polling system
3. Build an async task queue
4. Create a promise-based cache system
5. Implement retry mechanism for failed requests
