JavaScript
JS04

JS04 Exercises

Practical Exercises

  1. Send a GET request to https://jsonplaceholder.typicode.com/todos/1 (opens in a new tab) and retrieve the JSON object using the fetch function. Use the promise-based approach.
fetch('https://jsonplaceholder.typicode.com/todos/1')
    .then(response => response.json())
    .then(data => {
        console.log(data); // Process your data here
    })
  1. Send a GET request to https://jsonplaceholder.typicode.com/todos/1 (opens in a new tab) and retrieve the JSON object using the fetch function. Use async/await.
async function fetchData() {
    const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
    const data = await response.json();
    console.log(data); // Process your data here
}
 
fetchData();
 
  1. What possible errors can happen during the fetch and how would you handle them? Add full error handling to your previous solutions.

Possible errors during a fetch operation in JavaScript include network failures, HTTP error statuses, and JSON parsing errors. To handle them, use .then() to check for HTTP errors (response.ok), .json() for parsing JSON responses, and .catch() to catch and handle all types of errors, including network issues.

fetch('https://example.com/data')
  .then(response => {
    // Check if the response is ok (status in the range 200-299)
    if (!response.ok) {
      throw new Error('Network response was not ok: ' + response.statusText);
    }
    return response.json();
  })
  .then(data => {
    // Process your data here
    console.log(data);
  })
  .catch(error => {
    // Handle any error that occurred in any of the previous promises
    console.error('There was a problem with the fetch operation: ', error.message);
  });
 
async function fetchData() {
    try {
        const response = await fetch('https://jsonplaceholder.typicode.com/todos/1');
 
        // Check if the response is ok (status in the range 200-299)
        if (!response.ok) {
            throw new Error('HTTP error! status: ' + response.status);
        }
 
        const data = await response.json();
        console.log(data); // Process your data here
    } catch (error) {
        // Handle any error that occurred in the previous block
        console.error('Error:', error.message);
    }
}
 
  1. Send three simultaneous requests to:
async function fetchMultipleData() {
    try {
        const urls = [
            'https://jsonplaceholder.typicode.com/todos/1',
            'https://jsonplaceholder.typicode.com/todos/2',
            'https://jsonplaceholder.typicode.com/todos/3'
        ];
 
        const requests = urls.map(url => fetch(url));
        const responses = await Promise.all(requests);
 
        // Check for HTTP errors and parse JSON
        const data = await Promise.all(
            responses.map(response => {
                if (!response.ok) {
                    throw new Error(`HTTP error! status: ${response.status}`);
                }
                return response.json();
            })
        );
 
        console.log(data); // Process your data here
    } catch (error) {
        console.error('Error:', error.message);
    }
 
}
 
fetchMultipleData();
 

Theoretical Exercises

  1. Why do we need to write asynchronous code in the first place?

Asynchronous code allows for non-blocking operations, enabling the program to execute other tasks while waiting for an asynchronous operation (like network requests, file I/O) to complete, thus improving efficiency and responsiveness.

  1. What is a promise?

A promise is an object representing the eventual completion or failure of an asynchronous operation. It allows you to associate handlers with an asynchronous action's success value or failure reason.

  1. What does then return?

The then method returns a new promise. It takes up to two arguments: callback functions for the success and failure cases of the promise.

  1. How does promise chaining work?

Promise chaining works by returning a promise in each then() call. This allows sequential execution of asynchronous operations, with each step waiting for the previous one to complete before starting.

  1. Why do we usually prefer async/await over promise chains?

async/await is preferred for its cleaner and more readable syntax, resembling synchronous code flow. It simplifies the handling of asynchronous operations and makes error handling more straightforward compared to promise chains.

  1. You need to perform asynchronous operations that depend on each other. Should you chain promises with then or use Promise.all / Promise.allSettled?

Chain promises with then when asynchronous operations depend on each other, as each operation may need the result of the previous one.

  1. You need to perform asynchronous operations that do not depend on each other. Should you chain promises with then or use Promise.all / Promise.allSettled?

Use Promise.all or Promise.allSettled for asynchronous operations that do not depend on each other, as these methods allow for concurrent execution and efficiency.

  1. What is the difference between Promise.all and Promise.allSettled?

Promise.all rejects immediately upon any of the input promises rejecting. In contrast, Promise.allSettled waits for all promises to settle (either fulfilled or rejected) and returns an array of objects describing the outcome of each promise.