Использование Promise в JavaScript

Использование Promise в JavaScript

Promise — это обещание используется для отложенных и асинхронных вычислений.

Имеет 3 состояния:

  • ожидание (pending): начальное состояние, не выполнено и не отклонено.
  • выполнено (fulfilled): операция завершена успешно.
  • отклонено (rejected): операция завершена с ошибкой.

Что бы понять как с ним работать, рассмотрим простой пример: пользователь зашел на типовую страницу со статьей, необходимо проверить асинхронно аутентификацию, получить данные и отобразить их на странице.

Из начальных условий мы имеем:

  • На стороне frontend хранится уникальный идентификатор сессии
  • К идентификатору привязан в базе сам пользователь
  • К пользователю привязаны, к примеру, лента новостей, аватар и какие-то еще уникальные данные

Соответственно начнем с простого,  отправку http запросов на API сервера методом fetch для получения данных, в которые будут передавать URL.

 

//проверка серверных ошибок
val status = res => (res.status !== 200) ? //проверяем вернувшийся запрос
    Promise.reject(new Error(res.statusText)) : // возврат статус ошибки
    Promise.resolve(res); // возврат результата
//преобразование json в обьект
val json = res => res.json();
//функци отправка данных, fetch - интерфейс для доступа и обработки частей протокола HTTP
val myFetch = (url, data) => fetch( url, { //url куда будет отправлен ajax запрос
        method: "POST",  //метод отправки данных
        params: data //параметры передаваемые серверу
    })
    .then(status) // обработка результата запроса
    .then(json) // преобразование данных в json

Создано 3 функции:

  • myFetch — основная функция, получает на вход URL для запроса и данные которые будут отправлены методом POST
  • json — по API нам возвращается строка, которую необходимо преобразовать в JSON формат, данная функция возвращает результат преобразования
  • status — функция проверяющая какой ответ пришел от сервера, если статус ответа не 200 — выводим ошибку

Переходим к основной части скрипта

//запрос на получение данных пользователя
var usr = myFetch (
    "https://tarsy.club/tutorial.php?usr=true",  //url api
    { hash: sessionStorage.getItem('hash') }  //данные
)
.then( usr => {
    //вывод данных пользователя в отладочной консолье
    console.log(usr);
})
.catch( // перехват ошибки и вывод
    err => console.error(err)
)

Мы записываем в переменную «usr» результат полученных данных после отправки по url api значения hash для поиска активного пользователя, так же в методе «then» можно поставить дополнительный обработчик который будет отрабатывать после успешного получения данных и преобразовании их в json, либо запустится обработчик «catch», если возникнет ошибка.

Тем самым получены дынные пользователя, теперь необходимо получить дополнительные параметры пользователя относящиеся к новостной ленте, комментариям и другим параметрам. Для увеличения производительности это надо делать асинхронно, поэтому сразу после вызова функции «myFetch» добавим еще один «then», в котором будут получены данные. А также надо добавить дополнительную проверку на корректность данных:

.then( async usr => {
    //проверка наличия уникального идентификатора
    if( !usr.uid ){
        throw new Error('#error_001');
    }
    //подгружаем асинхронно данные
    usr.components = await Promise.all([ //ожидаем завиршение всех внутренних промисов
            myFetch( //получение параметров
                "https://tarsy.club/tutorial.php?parent=true", //url api
                { usr_uid: usr.uid } //данные
            ),
            myFetch( //получение коментарий
                "https://tarsy.club/tutorial.php?comment=true", //url api
                { usr_uid: usr.uid } //данные
            ),
            myFetch( //получение новостей
                "https://tarsy.club/tutorial.php?news=true", //url api
                { usr_uid: usr.uid } //данные
            )
        ])
        .then( result => console.log(result) )
        .catch( error => console.error(error) );
    return usr;
} )

В данной части вызывается анонимная асинхронная функция, куда передается объект с результатом выполнения «myFetch».

Первым действие проверяем наличие уникального идентификатора пользователя, если его нет, то выводим исключение и завершаем обработку.

Следующим действием создаем «Promise», ожидающий полную асинхронную загрузку все внутренних данных, которые записываем в параметр «components» пользователя.

В данном блоке мы имеем следующие

  • .all — ожидает ответ от всех внутренних промисов
  • async — показывает что функция запускается асинхронно
  • await — показываем что надо дождаться результата вычисления
  • new Promise(…) — промесы с различным временем на выполнение
  • .then — вызов функции при успешной выполнении предыдущей цепочки
  • .catch — вызов функции при не успешной выполнении предыдущей цепочки

Полный получившийся скрипт получения данных пользователя через использования Promise и fetch получился следующий:

//проверка серверных ошибок
var status = res => (res.status !== 200) ? //проверяем вернувшийся запрос
    Promise.reject(new Error(res.statusText)) : // возврат статус ошибки
    Promise.resolve(res); // возврат результата
//преобразование json в обьект
var json = res => res.json();
//функци отправка данных, fetch - интерфейс для доступа и обработки частей протокола HTTP
var myFetch = (url, data) => fetch( url, { //url куда будет отправлен ajax запрос
        method: "POST",  //метод отправки данных
        params: data //параметры передаваемые серверу
    })
    .then(status) // обработка результата запроса
    .then(json) // преобразование данных в json
//запрос на получение данных пользователя
var usr = myFetch (
    "https://tarsy.club/tutorial.php?usr=true",  //url api
    { hash: sessionStorage.getItem('hash') }  //данные
)
.then( async usr => {
    //проверка наличия уникального идентификатора
    if( !usr.uid ){
        throw new Error('#error_001');
    }
    //подгружаем асинхронно данные
    usr.components = await Promise.all([ //ожидаем завиршение всех внутренних промисов
            myFetch( //получение параметров
                "https://tarsy.club/tutorial.php?parent=true", //url api
                { usr_uid: usr.uid } //данные
            ),
            myFetch( //получение коментарий
                "https://tarsy.club/tutorial.php?comment=true", //url api
                { usr_uid: usr.uid } //данные
            ),
            myFetch( //получение новостей
                "https://tarsy.club/tutorial.php?news=true", //url api
                { usr_uid: usr.uid } //данные
            )
        ])
        .then( result => console.log(result) )
        .catch( error => console.error(error) );
    return usr;
} )
.then( usr => {
    //вывод данных пользователя в отладочной консолье
    console.log(usr);
})
.catch( // перехват ошибки и вывод
    err => console.error(err)
)

 

Полезные ссылки:

анимация демонстрирующая загрузку данных

github страница для тестирования promise

Опубликовано:
Пожертвование
На развите проекта, продление хостинга и на корм бобику - Дикуше :)