Изучение внутренней работы setTimeout(), Promises и Async/Await для эффективного асинхронного программирования в JavaScript

Понимание смысла асинхронного JS

АсинхронныйJavaScript позволяет нам выполнять несколько задач одновременно, не дожидаясь завершения каждой задачи, прежде чем переходить к следующей. Давайте представим это на примере, представьте себе фабрику, которая производит разные продукты с несколькими сборочными линиями. При синхронном программировании рабочие выполняют один заказ, прежде чем перейти к следующему, что приводит к длительному времени ожидания клиентов. В асинхронном программировании рабочие могут работать над несколькими заказами одновременно, что приводит к более быстрому выполнению заказов.

В асинхронном JavaScript сборочные линии представляют асинхронные функции, а заказы — задачи. Когда задача назначается сборочной линии, она добавляется в очередь для асинхронного выполнения. Рабочие сборочной линии начинают работать над задачами в очереди, но они не ждут завершения задачи, прежде чем перейти к следующей. Это означает, что когда задача включает в себя трудоемкую операцию, такую ​​как вызов API*, работник сборочной линии не ждет завершения вызова API*, прежде чем перейти к следующей задаче.

Какая разница, что делает асинхронный JS?

Асинхронный JavaScript имеет решающее значение для веб-разработчиков и крупных компаний-разработчиков программного обеспечения по нескольким причинам.

  • Это повышает производительность вашего веб-сайта, позволяя выполнять утомительные операции в фоновом режиме.
  • Теперь ваш сайт может обрабатывать несколько запросов
  • Вы сможете хорошо организовать свой код

Что исследования говорят нам о тенденциях?

По данным Google Insights, среднее время загрузки веб-сайта для мобильных устройств составляет около 22 секунд, а среднее время загрузки веб-сайта для настольных компьютеров — около 15 секунд.

Однако исследования показали, что пользователи готовы ждать загрузки веб-сайта всего до 3 секунд, прежде чем они начнут его покидать.

Итак, вы видите, насколько важно отображать веб-страницу как можно быстрее, чтобы увеличить привлечение клиентов.

Давайте перейдем к самой веселой части: CODDEEEEE!

Визуализация setTimeout()

Давайте посмотрим на этот код:

Журналы следующего кода:

Итак, мы знаем, что JS выполняется построчно сверху вниз, и ожидаем, что «1-й» должен быть зарегистрирован в начале. Но в конце концов этого не произошло, и вместо этого, наконец, вошли в систему.

Давайте посмотрим, что происходит:

Наша первая строка кода с setTimeout() удерживает строку «1st» от ведения журнала консоли в течение 1000 миллисекунд, что дает достаточно времени для следующих 3 строк, чтобы зарегистрировать свои значения. Теперь вы можете подумать, зачем вообще кому-то нужна такая встроенная функция?

Представьте себе веб-сайт, который требует отображать некоторые предложения для клиентов, если они проводят определенное время на своем веб-сайте для создания клиентской базы. Как мы могли это сделать? Что ж, давайте посмотрим на некоторый исходный код для этого:

function showPopup(delay, callback) {
  setTimeout(callback, delay);
}

// Set the amount of time to wait before showing the popup (in milliseconds)
const popupDelay = 30000; // 30 seconds

// Define the callback function to show the offer popup
function showOfferPopup() {
  // Get a reference to the popup element
  const modal = document.getElementById('offer-popup');

  // Show the popup
  modal.style.display = 'block';
}

// Call the showModalPopup function with the delay and callback function
showPopup(popupDelay, showOfferPopup);

У нас есть функция showPopup(), которая принимает обратный вызов и задержку в качестве аргументов, а функция showOfferPopup() добавляет всплывающее окно в DOM, когда setTimeout() срабатывает после 30 секунд прокрутки сайта пользователем.

Визуализация обещаний

Согласно MDN, Promise — это встроенный объект JavaScript, который представляет возможное завершение (или сбой) асинхронной операции и ее результирующее значение. Промисы предоставляют способ обработки асинхронных операций более структурированным и интуитивно понятным способом. На этот раз давайте воспользуемся концепцией Promise в нашем коде:

const url = 'https://jsonplaceholder.typicode.com/posts'
function fetchData(url) {
  return new Promise((resolve, reject) => {
    fetch(url)
      .then(response => {
        if (!response.ok) {
          throw new Error(`HTTP error! Status: ${response.status}`);
        }
        return response.json();
      })
      .then(data => {
        resolve(data);
      })
      .catch(error => {
        reject(error);
      });
  });
}

fetchData(url)
  .then(data => {
    console.log(data);
  })
  .catch(error => {
    console.error(error);
  });

Предположим, мы пытаемся написать GET-запрос и получить данные, содержащие изображения. В этом коде наш fetchData() вернет обещание, которое, в свою очередь, вернет нам ответ, который будет выполняться им в фоновом режиме, не мешая текущему времени загрузки веб-сайта.

Этот вызов API предоставляет нам 100 идентификаторов, но в реальной жизни вызов API будет состоять из 1000 идентификаторов, которые, если их не обрабатывать асинхронно, остановят рендеринг всего веб-сайта и значительно увеличат время загрузки.

Даже если ответ будет неудачным, он вернет нам ошибку, соответствующую сбою. Мы возвращаем наши данные в формате JSON, и наш .then() записывает данные в нашу консоль.

В конечном счете, JavaScript является однопоточным, поэтому он не может выполнять несколько задач одновременно. Асинхронные операции с использованием Promise позволяют разработчикам выполнять трудоемкие задачи, такие как выборка данных из API или загрузка больших файлов, не блокируя основной поток.

Визуализация асинхронного/ожидания

Это новая концепция, которая была очень нужна в JS. Это синтаксис для обработки асинхронного кода в JavaScript. Ключевое слово async используется для пометки функции как асинхронной, а ключевое слово await используется для приостановки выполнения функции до тех пор, пока промис не будет разрешен.

Давайте посмотрим пример:

async function getData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    return data;
  } catch (error) {
    console.error(error);
  }
}

getData().then(data => {
  console.log(data);
});

В этом примере мы определили асинхронную функцию getData(), которая извлекает некоторые данные из API с помощью метода fetch(). Затем мы используем ключевое слово await для ожидания ответа от API перед преобразованием его в JSON с помощью метода response.json(). Наконец, мы возвращаем проанализированные данные из функции getData().

Мы используем блок try/catch для обработки любых ошибок, которые могут возникнуть во время работы методов fetch() и .json(). Если возникает ошибка, мы записываем ее в консоль.

Чтобы вызвать функцию getData(), мы используем метод then() для обработки возвращаемых данных. Выводим данные в консоль.

Использование async/await делает асинхронный код более читабельным и понятным. Это позволяет разработчикам писать асинхронный код, похожий на синхронный код, что может помочь снизить когнитивную нагрузку и упростить обслуживание кода.

Заключение!

В заключение, асинхронный JavaScript — это мощный инструмент, который позволяет нам писать эффективный и отзывчивый код. Используя такие функции, как async/await, setTimeout и обещания, мы можем выполнять несколько задач одновременно, не дожидаясь завершения каждой задачи. Это может значительно повысить производительность наших приложений и улучшить взаимодействие с пользователем. Обладая глубоким пониманием асинхронного программирования, мы можем писать более эффективные и масштабируемые приложения.

console.log("Coding for Life 🍻")