Статьи

Обзор обещаний JavaScript

Этот учебник охватывает основы обещаний JavaScript, показывая, как вы можете использовать их в разработке JavaScript.

Концепция обещаний не нова для веб-разработки. Многие из нас уже использовали обещания в форме библиотек, таких как Q, when.js, RSVP.js и т. Д. Даже в jQuery есть нечто, называемое отложенным объектом , что похоже на обещание. Но теперь у нас есть встроенная поддержка обещаний в JavaScript, что действительно здорово.

обзор

Объект Promise Это позволяет писать асинхронный код более синхронно. Например, если вы используете API обещаний для выполнения асинхронного вызова удаленной веб-службы, вы создадите объект Promise Предостережение заключается в том, что фактические данные еще не доступны. Он станет доступным, когда запрос будет завершен и ответ будет возвращен из веб-службы. Между тем объект Promise Кроме того, вы можете прикрепить обратные вызовы к объекту Promise

API

Для начала давайте рассмотрим следующий код, который создает новый объект Promise

 const promise = new Promise((resolve, reject) => {
  //asynchronous code goes here
});

Мы начнем с создания нового объекта Promise Обратный вызов принимает два аргумента: resolvereject Весь ваш асинхронный код идет внутри этого обратного вызова. Если все выполнено успешно, обещание выполняется путем вызова resolve() В случае ошибки reject()Error Это указывает на то, что обещание отклонено.

Теперь давайте создадим что-то простое, которое показывает, как используются обещания. Следующий код выполняет асинхронный запрос к веб-службе, которая возвращает случайную шутку в формате JSON. Давайте рассмотрим, как здесь используются обещания:

 const promise = new Promise((resolve, reject) => {
  const request = new XMLHttpRequest();

  request.open('GET', 'https://api.icndb.com/jokes/random');
  request.onload = () => {
    if (request.status === 200) {
      resolve(request.response); // we got data here, so resolve the Promise
    } else {
      reject(Error(request.statusText)); // status is not 200 OK, so reject
    }
  };

  request.onerror = () => {
    reject(Error('Error fetching data.')); // error occurred, reject the  Promise
  };

  request.send(); // send the request
});

console.log('Asynchronous request made.');

promise.then((data) => {
  console.log('Got data! Promise fulfilled.');
  document.body.textContent = JSON.parse(data).value.joke;
}, (error) => {
  console.log('Promise rejected.');
  console.log(error.message);
});

В предыдущем коде обратный вызов конструктора Promise Здесь мы просто создаем Ajax-запрос к https://api.icndb.com/jokes/random , который возвращает случайную шутку. Когда JSON-ответ получен от удаленного сервера, он передается для resolve() В случае любой ошибки reject()Error

Когда мы создаем экземпляр объекта Promise В нашем случае мы ожидаем, что некоторые данные будут возвращены из удаленного сервиса в будущем. Итак, как мы узнаем, когда данные станут доступны? Здесь используется Promise.then() Эта функция принимает два аргумента: обратный вызов успеха и обратный вызов сбоя. Эти обратные вызовы вызываются, когда Promise Если обещание было выполнено, обратный вызов успеха будет запущен с фактическими данными, которые вы передали для resolve() Если обещание было отклонено, будет вызван обратный вызов сбоя. Все, что вы передали reject()

Попробуйте этот пример CodePen . Чтобы просмотреть новую случайную шутку, нажмите кнопку RERUN в нижнем правом углу вставки. Кроме того, откройте консоль браузера, чтобы вы могли видеть порядок выполнения различных частей кода.

Обратите внимание, что обещание может иметь три состояния:

  • в ожидании (не выполнено или отклонено)
  • выполнены
  • отвергнуто

Свойство Promise.status Как только обещание отклонено или выполнено, этот статус постоянно связывается с ним. Это означает, что обещание может быть выполнено или провалено только один раз. Если обещание уже выполнено, и позже вы присоединяете к нему then() Итак, в мире обещаний нам не интересно знать, когда обещание будет выполнено. Мы обеспокоены только окончательным результатом обещания.

Цепные обещания

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

 function getPromise(url) {
  // return a Promise here
  // send an async request to the url as a part of promise
  // after getting the result, resolve the promise with it
}

const promise = getPromise('some url here');

promise.then((result) => {
  //we have our result here
  return getPromise(result); //return a promise here again
}).then((result) => {
  //handle the final result
});

Сложность в том, что, когда вы возвращаете простое значение внутри then()then() Но если вы возвращаете обещание внутри then()then()

Обработка ошибок

Вы уже знаете, что функция then() Второй будет вызван, если обещание было отклонено. Но у нас также есть функция catch() Посмотрите на следующий код:

 promise.then((result) => {
  console.log('Got data!', result);
}).catch((error) => {
  console.log('Error occurred!', error);
});

Это эквивалентно:

 promise.then((result) => {
  console.log('Got data!', result);
}).then(undefined, (error) => {A
  console.log('Error occurred!', erroAr);
});

Обратите внимание, что если обещание было отклонено, а then()then()catch() Помимо явного отклонения обещания, catch()Promise Таким образом, вы также можете использовать catch() Обратите внимание, что мы могли бы использовать try...catchcatch()

Вывод

Это было лишь краткое введение в новый интерфейс JavaScript Promises. Очевидно, что это позволяет нам очень легко писать асинхронный код. Мы можем продолжать как обычно, не зная, какое значение будет возвращено из асинхронного кода в будущем. В API есть еще кое-что, что здесь не освещалось. Чтобы узнать больше об обещаниях, ознакомьтесь с моей последующей статьей « Более глубокое погружение в обещания JavaScript» , а также с этими замечательными ресурсами: