Многообещающая функция асинхронного Javascript
Обещания могут быть сложным делом. Как однопоточный язык, Javascript сильно выигрывает от асинхронности, обеспечиваемой промисами. Во многих отношениях обещания необходимы для правильного выполнения кода и загрузки ресурсов. Это то, что позволяет программе извлекать ресурсы из различных локальных и удаленных репозиториев, не беспокоясь о разном времени загрузки этих ресурсов.
Когда дело доходит до промисов, есть три термина, которые часто можно услышать при работе с ними:
- Исполнено — действие Обещания выполнено успешно.
- Отклонено — действие обещания не выполнено
- В ожидании — действие Обещания еще не урегулировано
Часто люди ссылаются на четвертый термин «урегулировано», что означает, что ваше Обещание либо выполнено, либо отклонено, или, другими словами, оно больше не находится в ожидании.
При работе с промисами важно учитывать поведение программы перед лицом выполнения промиса и отклонения промиса. Но прежде чем мы углубимся в это, давайте немного поговорим о синтаксисе.
const promise = new Promise(function (resolve, reject){ //Execute some code if (//Conditional to see whether to resolve or reject) { resolve("Working!") } else { reject(Error("Not working!")) } }
В приведенном выше коде создается обещание, которое принимает функцию обратного вызова в качестве аргумента. Эта функция, в свою очередь, имеет два аргумента, resolve
и reject
, которые соответственно определяют возвращаемое значение в случае, если обещание было выполнено или отклонено. В этом случае экземпляр Promise, созданный выше, вернет «Working!» если он выполнен или ошибка с сообщением «Не работает!» если оно будет отклонено.
Итак, мы можем сделать с экземпляром обещания? Сцепите несколько функций!
promise.then(function(res){ //Do some stuff if fulfilled }, function(err){ //Do some stuff if rejected })
then
— это метод экземпляра объектов Promise, который принимает до двух параметров: функцию, которая запускается в случае, если обещание было выполнено, и функцию, которая запускается в случае, если обещание было отклонено. В этом примере выполненное обещание будет передавать строку, устанавливающую res
в «Работает!»; отклоненное обещание передаст ошибку, установив err
в объект Error с сообщением «Не работает!» Затем каждая из функций может обрабатывать логику успеха или неудачи и возвращать значение. Если другой then
связан, возвращаемое значение любой функции, которая была выполнена, будет передано в качестве аргумента следующему then
, который связан с ним. И так далее!
Другой важный метод экземпляра промиса для работы с отклоненными промисами — это catch
.
promise.catch(rejectionCallback(err))
По большей части catch
— это просто синтаксический сахар для
promise.then(res => res, rejectionCallback(err))
Вышеупомянутое обещание связано с then
, который имеет обратный вызов успеха, который просто передает разрешенное значение вперед, по сути ничего не делая, и обратный вызов отклонения. catch
делает то же самое, но с некоторыми важными отличиями. Рассмотрим следующий код:
// promise -> then(1 arg) -> catch promise.then(resolveCallback(res)).catch(rejectionCallback) // promise -> then(2 args) promise.then(resolveCallback(res), rejectionCallback(err))
Обычно отклоненное промис пропускает все последующие вызовы then
без второго аргумента (обратный вызов отклонения), пока не найдет либо а) then
со вторым аргументом, либо б) вызов catch
.
Разница между цепочкой catch
и передачей второго аргумента then
заключается в том, что последний не может поймать ошибку, которая существует в выполненном обратном вызове. С другой стороны, catch
может перехватывать ошибки из исходного промиса, а также из предыдущего вызова then
. Помимо того, что это выглядит намного аккуратнее, это дает нам больше возможностей для проверки ошибок.
Предостережение с получением
До сих пор я работал с промисами только в контексте метода fetch
. Если вы раньше работали с fetch
, то знаете, что fetch
возвращает Promise после отправки запроса и получения ответа. Следует учитывать, что fetch
не будет отклоняться при получении ошибок ответа, таких как 404 или 500; fetch
будет отклоняться только в том случае, если соединение с сервером прервано. Таким образом, обработка ошибок ответа не может выполняться вызовами catch
, а вместо этого должна обрабатываться вызовами then
. Это важное соображение при создании веб-приложений, особенно когда ваше приложение использует вызовы к другим серверам и API.
Источники
Собеседование по изучению JavaScript: что такое обещание?
«Собеседование по изучению JavaScript – это серия сообщений, предназначенных для подготовки кандидатов к ответам на распространенные вопросы, которые они задают… среда.com»