作成日: 2021/05/19
1

Javascript - Async Functions

We can create and use promises, but if you really want to reduce complex code, you need to understand about the asynchronous functions.

First concept

All functions that return promises can be named asynchronous functions.

For example.

// Promised function `getUsers`
// Take the limit of users returned
// Return a Promise that fetches users
function getUsers(limit = 10) {
  // Create and return a new Promise with the task
  return new Promise((resolve, reject) => {
    // Define parameters to the fetch function
    const url = `https://randomuser.me/api?results=${limit}`;

    // Call the function fetch with the parameters (it's an another promise)
    fetch(url)
      .then((response) => {
        // When you have the reponse
        // Check if it's valid
        if (!response.ok) {
          // Throw out an error if response is not good
          throw new Error(`Error in ${url}`);
        }

        // Call in chain the promise to convert the response in JSON
        return response.json();
      })
      .then((data) => {
        // When you have the result of the previous promise-chain
        // Extract the results (this is the users array)
        // and resolve the promise with this value
        resolve(data.results);
      })
      .catch((error) => {
        // If any error was raised in some part of the promise-chain
        // Reject the promise with the error (error propagation)
        reject(error);
      });
  });
}

// Call the promise-function with parameters
getUsers(5)
  .then((users) => {
    // When you have the result (The resolve argument)
    // Display the users in the console
    console.log("Users", users); // [{gender: "female", name: { first: "Ana", ... }, ...}, ...]
  })
  .catch((error) => {
    // If any error was happened display it in the console
    console.log(`Error happens: ${error}`);
  });

In the above code, we can see 3 important parts.

  1. Define a promise-function called getUsers with some params (users limit).
  2. Inside the function, return a new promise. Into the promise, we chain a fetch-promise and resolve the promise created with the final result of the fetch (or reject with the throws error).
  3. We called the promise-function (same as fetch-function) with parameters and the then and catch callbacks.

The problem with promise-functions is the problem called CALLBACK HELL. The code is very ugly and complex.

Second Concept

We can create an async-function by defining asynchronous operations and waiting to finalize. Think as you create a linear-promise-function.

async function getUsersAsync(limit = 10) {
  const url = `https://randomuser.me/api?results=${limit}`;

  // `fetch` is a promise-function, await for the result (response object)
  const response = await fetch(url);

  if (!response.ok) {
    // Server response with not good news, but what?
    // Await for transform the response to text
    const error = await response.text();
    // Raise a new error with the server response
    // This is the final result of the function (like as reject)
    throw new Error(error);
  }

  // Continue here (not thrown)

  // Await to convert the response in JSON object
  const data = await response.json();

  // Extract the users from the resulting data
  const users = data.results;

  // This is the final result of the function (like as resolve)
  return users;
}

// Create another async-function to consume async or promise functions
async function displayUsers() {
  // Await for the result (the users)
  const users = await getUsersAsync();

  // Display them
  console.log("Users Async", users);
}

// This is an auto-executable async-function (<function>)();
(async () => {
  // We can clausure and handle the error with a linear `try-catch`
  try {
    // Try to display async fetch users
    await displayUsers();
  } catch (error) {
    // If error has raised, handle it.
    console.log(`Handle error: ${error}`);
  }
})();

In the above code, we can see 3 important parts.

  1. Define async-function by syntax async function <name>(<params>) { <body> }.
  2. Await for other async-functions or promises by sintax await <async function call> or await <promise>.
  3. Handle errors with try-catch code by syntax try { <async linear expressions> } catch(error) { <handle linear expressions> }.

Now you are ready to use Promises and Async Functions.

Let's do it

See the full code on codesandbox (see the results and live demo).
Edit async-functions

Algorithms and mathematics merge with artificial intelligence in a heightened zen state, to make way for the dragon.