February 12, 2024

V8, Libuv, and Async in JavaScript

JavaScript is a Synchronous language

JavaScript is a compiled language and is executed by the V8 engine.

V8 Engine

V8 Engine and Handling Asynchronous Operations

Libuv library in JavaScript Allows

Event Loop

Event Loop

Async Function

const getData = () => {
  const data = {
    username: "Natalia",
    userLastName: "Sabadysh",
    id: 1,
  };
 
  return Promise.resolve(data);
};
 
console.log(getData()); // Promise
 
getData().then((data) => console.log(data));
// data: { username: 'Natalia', userLastName: 'Sabadysh', id: 1 }

❌ Promise Hell

We can see the problem when we have multiple requests that rely on each other.

const getUser = () => {
  const data = {
    username: "Natalia",
    userLastName: "Sabadysh",
    id: 1,
  };
 
  return Promise.resolve(data);
};
 
const getType = (id) => {
  // .. logic to find the type based on the id
  const data = {
    type: "developer",
    id: 1,
  };
 
  return Promise.resolve(data);
};

Example with Promise

const getEmployInfo = () => {
  // Promise Hell
  return getUser().then((user) => {
    return getType(user.id).then((typeInfo) => {
      return {
        username: user.username + " " + user.userLastName,
        type: typeInfo.type,
      };
    });
  });
};
 
getEmployInfo().then((data) => console.log(data));

Example with Async/Await

const getEmployInfo = async () => {
  try {
    const user = await getUser();
    const typeInfo = await getType(user.id);
 
    return {
      username: `${user.username} ${user.userLastName}`,
      type: typeInfo.type,
    };
  } catch (error) {
    console.error("Error getting employee information:", error);
  }
};

Example Object methods with Async/Await

const user = {
  async getUser() {},
  async updateUser(updatedData) {},
};
 
// Example usage:
await user.getUser();
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
 
const getUserData = async () => {
  const data = {
    user: "Natalia Sabadysh",
    type: "Developer",
    id: 1,
  };
 
  await delay(1000); // Simulate delay
  return data;
};
 
const getOrderData = async (userId) => {
  await delay(1000);
  return {
    orderId: 123,
    userId: userId,
    items: ["item1", "item2"],
  };
};
 
const fetchUserDataAndOrder = async () => {
  console.time("Start timer"); //Timer label for consistency
 
  const userData = await getUserData();
  const orderData = await getOrderData(userData.id);
 
  console.timeEnd("Start timer");
 
  return { userData, orderData };
};
 
fetchUserDataAndOrder().then((data) => console.log(data));

Multiple calls

// 1)await/await + Promise.all
// 2)await/await + Promise.race
// 3)await/await + Promise.allSettled -  fulfilled or rejected
 
const fetchData = async () => {
  try {
    const data = await Promise.all([
      getUserData(),
      getProductData(),
      getOrderData(),
    ]);
 
    return { userData: data[0], productData: data[1], orderData: data[2] };
  } catch (error) {
    throw error;
  }
};

await/await + Error Handler try catch

 
// 1- use case
fetchData.then(data=> ).catch(error=>console.log('Error fetching data:')
// 2- use case
 
const some_func = () => {
    try {
    const data = await fetchData();
    console.log("Fetched data successfully:", data);
  } catch (error) {
    console.error("Error fetching data:", error);
  }
}