Основы JavaScript Promise API | Кодементор

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

Почему обещания?

При работе с ситуацией, когда трудно определить, когда задача будет завершена, потому что это зависит от внешней службы, которую мы не контролируем. Объекты промисов — это средство для асинхронного решения этих проблем с помощью эффективного API. Раньше в JavaScript мы использовали обратные вызовы для обработки асинхронных задач, однако у обратных вызовов было много проблем, когда дело доходило до обработки асинхронных задач, которые зависят друг от друга, и, следовательно, родились промисы.
Давайте сделаем new Promise

const someTask = new Promise((resolve, reject) => {})

Самый простой способ создать промис — это вызвать new Promise конструктор. Давайте посмотрим на пример

3 состояния обещания

  • Ожидание — когда вы только что создали обещание, оно будет отложено.
  • Выполнено / Решено — Когда обещание выполнено
  • Отклонено — когда произошла ошибка и обещанное значение не может быть определено

Итак, мы создаем экземпляр new Promise и передать функцию с 2 аргументами resolve а также reject.Что resolve а также reject можно спросить. По сути resolve следует вызывать, когда задача была успешно выполнена и reject следует вызывать, если задача не удалась. Давайте продолжим наш пример. Мы будем использовать setTimeout для имитации асинхронной задачи, выполнение которой займет некоторое время. Эта задача в основном займет около 500 мс.

const calculation = new Promise((resolve, reject) => {
  setTimeout(() => resolve(1 + 1), 500)
})

По сути, внутри обещания вы вызываете разрешение, когда задача завершена. Это в основном то, как обещание узнает, что задача была «решена».

После того, как вы определили промис, вам нужно получить результат этой функции. Следующий код запишет результат в консоль. В этом случае мы добавляем 1 + 1, поэтому мы вернем 2 на консоль.

calculation.then(result => console.log(result))
=> 2

Отклонение результата (обработка ошибок)

Скажем, например, у нас есть следующее, мы пытаемся выяснить, может ли кто-то пить кофе или нет.

const age = 7
const user = {name: 'zack'}

const checkCoffeeAble = new Promise((resolve, reject) => {
  if (age >= 18) {
    resolve(user)
  } else {
    reject("cannot have coffee")
  }
})

const canHaveCoffee = (result) => {
  localStorage('coffee_drinker', result.name)
}

const cannotHaveCoffee = (result) => {
  console.log(result)
}

checkCoffeeAble.then(canHaveCoffee, cannotHaveCoffee)

В этом случае мы жестко задаем возраст, поэтому, вероятно, получим отклоненный результат на консоль. Но дело в том, что вы можете видеть, что мы по-прежнему обрабатываем отказы, используя then, мы просто передаем отклоненную функцию в качестве второго аргумента then. Мы также можем использовать такой захват.

checkCoffeeAble.then(canHaveCoffee).catch(cannotHaveCoffee)

Далее мы рассмотрим пример из реальной жизни, в котором мы фактически сделаем сетевой вызов, чтобы определить какой-то результат с помощью базовой логики.

Более надуманный пример

Допустим, мы хотим иметь возможность запрашивать github для популярного репо по имени темы, которое мы передаем в имени темы, и результат будет отображаться в dom. Таким образом, основной поток будет примерно таким.

  1. Позвоните в Github, используя fetch
  2. Получите данные из github и повторите их, используя карту внутри обещания.
  3. Отобразите результаты на странице.
  4. Если нет результатов, мы выводим сообщение об ошибке.

Причина, по которой мы делаем это таким образом,

  1. Мы не хотим просто использовать fetch, так как fetch уже возвращает Promise по умолчанию.
  2. Нам нужна какая-то рабочая нагрузка, которую можно решить с помощью нового промиса.
  3. Давайте setTimeout и console.log могут сделать довольно скучный пример.

Мы будем использовать обещание для обработки результатов и создания HTML-кода, который затем будем использовать для обновления dom. Здесь Код JS и codeandbox.

import "./styles.css";

const headers = {
  Accept: "application/vnd.github.mercy-preview+json"
};

const getResults = topic =>
  fetch(` {
    headers
  })
    .then(response => response.json())
    .then(body => body.items);

const renderItems = items =>
  new Promise((resolve, reject) => {
    if (Array.isArray(items) && items.length > 0) {
      const data = items.map(item => `<h2>${item.name}</h2>`).join("");

      resolve(data);
    } else {
      reject("<div>no results found try a different topic</div>");
    }
  });

const searchTopics = topic => {
  document.getElementById("app").innerHTML = "<h1>Loading...</h1>";

  getResults(topic)
    .then(renderItems)
    .then(html => {
      document.getElementById("app").innerHTML = `
        <div class="results">
          <h1>results for: ${topic}</h1>
          ${html}
        </div>
      `;
    })
    .catch(error => {
      document.getElementById("app").innerHTML = `
        <div class="error">${error}</div>
      `;
    });
};

// try passing in "89348598095380953" for error response
searchTopics("machine learning");

Основная функция, использующая пользовательский промис, находится здесь.

const renderItems = items =>
  new Promise((resolve, reject) => {
    if (items.length > 0) {
      const data = items.map(item => `<h2>${item.name}</h2>`).join("");

      resolve(data);
    } else {
      reject("<div>no results found try a different topic</div>");
    }
  });

Давайте немного разберем это в операторе if, мы проверяем, действительно ли сетевой вызов вернул результат. Если ничего не было возвращено, мы используем reject, если что-то было возвращено, мы повторяем и используем разрешение, когда итерация завершена.

Вот как это называется.

  getResults(topic)
    .then(renderItems)
    .then(html => {
      document.getElementById("app").innerHTML = `
        <div class="results">${html}</div>
      `;
    })
    .catch(error => {
      document.getElementById("app").innerHTML = `
        <div class="error">${error}</div>
      `;
    });

Сначала мы используем getResults(topic), затем мы передаем наше обещание renderItems как функцию обратного вызова, затем мы обрабатываем сценарий успеха, отображая результаты в div результатов, и если у нас нет возвращенных результатов, мы перехватываем и отображаем сообщение об ошибке. разд.

Заворачивать

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

Если у вас есть какие-либо вопросы / опасения по поводу этого поста, не стесняйтесь задать вопрос или оставить отзыв здесь.

Похожие записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *