.then() — JavaScript — Дока

  1. Кратко
  2. Как пишется
  3. Как понять
  4. На практике
    1. Николай Лопин советует

💡

Эта статья связана с понятием Promise.

Кратко

Скопировано

Метод then() используют, чтобы выполнить код после изменения состояния промиса.

Метод принимает два аргумента:

  • onFulfill — функция-колбэк, которая будет вызвана при переходе промиса в состояние «успех» fulfilled. Функция имеет один параметр, в который передаётся результат выполнения операции
  • onReject — функция-колбэк, которая будет вызвана при переходе промиса в состояние «ошибка» rejected. Функция имеет один параметр, в который передаётся информация об ошибке

Всегда возвращает новый промис.

Как пишется

Скопировано

// getPasswords() — асинхронная функция, которая возвращает промисgetPasswords(). then(  function (result) {    // что-то делаем с результатом операции    console.log('Все пароли:' + result)  },  function (err) {    // обрабатываем ошибку    console.error(err.message)  })
          // getPasswords() — асинхронная функция, которая возвращает промис
getPasswords().then(
  function (result) {
    // что-то делаем с результатом операции
    console.log('Все пароли:' + result)
  },
  function (err) {
    // обрабатываем ошибку
    console.error(err.message)
  }
)

Как понять

Скопировано

Обработка асинхронных операций через промис и then() очень похожа на работу с колбэками.

Так как then() всегда возвращает новый промис, то его удобно использовать для построения последовательностей асинхронных операций:

// запросим через API список домов из Игры престолов. Метод `fetch` возвращает промисfetch('https://www. anapioficeandfire.com/api/houses')  .then(function (response) {    // выполнится, когда от API придет ответ    // запустим асинхронную операцию парсинга JSON из ответа сервера    return response.json() // вернем из обработчика промис, к которому добавим then  })  .then(function (houses) {    // выполнится, когда JSON распарсится    return fetch(houses[0].overlord) // запросим данные о сюзерене этого дома  })  .then(function (response) {    // выполнится, когда от API придет ответ    return response.json()  })  .then(function (overlord) {    console.log(overlord.name)  })
          
// запросим через API список домов из Игры престолов. Метод `fetch` возвращает промис fetch('https://www.anapioficeandfire.com/api/houses') .then(function (response) { // выполнится, когда от API придет ответ // запустим асинхронную операцию парсинга JSON из ответа сервера return response.json() // вернем из обработчика промис, к которому добавим then }) .then(function (houses) { // выполнится, когда JSON распарсится return fetch(houses[0].
overlord) // запросим данные о сюзерене этого дома }) .then(function (response) { // выполнится, когда от API придет ответ return response.json() }) .then(function (overlord) { console.log(overlord.name) })

В коде выше, каждый вызов then() привязан к результату предыдущей операции. Такой код читается почти как синхронный.

На практике

Скопировано

Николай Лопин советует

Скопировано

🛠 then() в индустрии используется только для обработки успешного завершения операции, в варианте с одним аргументом:

getPasswords().then(function (result) {  // что-то делаем с результатом операции  console.log(`Все пароли: ${result}`)})
          
getPasswords().then(function (result) { // что-то делаем с результатом операции console.log(`Все пароли: ${result}`) })

Для обработки ошибок используют метод catch(). Такие цепочки читаются лучше:

getPasswords()  .then(function (result) {    console.log(`Все пароли: ${result}`)  })  .catch(function (error) {      console.log(`Ошибка: ${error.message}`)  })
          getPasswords()
  .then(function (result) {
    console.log(`Все пароли: ${result}`)
  })
  .catch(function (error) {
      console.log(`Ошибка: ${error.message}`)
  })

Если вы нашли ошибку, отправьте нам пул-реквест!

Во время отправки формы что-то пошло не так. Попробуйте ещё раз?

Promise

ctrl + alt +

.catch()

ctrl + alt +

Promise — отложенные и асинхронные вычисления

Promise(Обещание) — это объект который содержит будущее значение асинхронной операции. Например, если вы запрашиваете некоторые данные с сервера, промис обещает нам получить эти данные, которые мы сможем использовать в будущем.

Вначале промис имеет статус pending («ожидание»), затем – одно из: fulfilled («выполнено успешно») или rejected («выполнено с ошибкой🙅‍♂️»).

  1. Pending - Промис ожидает, если результат не готов. То есть, ожидает завершение чего-либо (например, завершения асинхронной операции).
  2. Fulfilled - Промис решен, если результат доступен. То есть, что-то завершило свое выполнение(например, асинхронная операция) и все прошло успешно.
  3. Rejected - Промиc отклонен, если произошла ошибка в процессе выполнения.

Видео​

Создание промиса​

Объект Promise создается🏗️ при помощи ключевого🗝️ слова new и своего конструктора. Конструктор Промисов принимает один аргумент, обратный вызов, также известный как исполнительная функция⚙️, которая принимает 2 обратных вызова,

resolve и reject.

Исполнительная функция⚙️ выполняется сразу же после создания🏗️ промиса. Промис становится выполненным при помощи вызова resolve(), а отклоненным при помощи reject().

const promise = new Promise((resolve, reject) => {
if (allWentWell) {
resolve('Все прошло отлично!')
} else {
reject('Что-то пошло не так')
}
})

resolve() и reject()

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

Чтобы снабдить функцию⚙️ функционалом⚙️ обещаний, нужно просто вернуть в ней объект Promise:

function myAsyncFunction(url) {
return new Promise((resolve, reject) => {
//код функции
})
}

Использование промиса​

Промисы используются при помощи методов then() и catch().

then​

Метод then используется для запуска функций⚙️ при положительном и отрицательном результате промиса.

Синтаксис📖 метода then:

promise. then(
function (result) {
/* обработает успешное выполнение */
},
function (error) {
/* обработает ошибку */
}
)

Первый 1️⃣ аргумент метода then – функция⚙️, которая выполняется, когда промис переходит в состояние «выполнен успешно», и получает результат.

Второй аргумент then – функция⚙️, которая выполняется, когда промис переходит в состояние «выполнен с ошибкой🙅‍♂️», и получает ошибку🙅‍♂️.

Пример метода then:

let promise = new Promise(function (resolve, reject) {
setTimeout(() => resolve('done!'), 1000)
})

// resolve запустит первую функцию, переданную в .then
promise.then(
result => alert(result), // выведет "done!" через одну секунду
error => alert(error) // не будет запущена
)

А в случае ошибки🙅‍♂️ в промисе – выполнится вторая:

let promise = new Promise(function (resolve, reject) {
setTimeout(() => reject(new Error('Whoops!')), 1000)
})

// reject запустит вторую функцию, переданную в . then
promise.then(
result => alert(result), // не будет запущена
error => alert(error) // выведет "Error: Whoops!" спустя одну секунду
)

Если нужно вывести только результат успешного выполения, то в then можно передать только одну функцию⚙️:

let promise = new Promise(resolve => {
setTimeout(() => resolve('done!'), 1000)
})

promise.then(alert) // выведет "done!" спустя одну секунду

catch​

Для отлова ошибок🙅‍♂️ используется метод catch. Его можно использовать вместо метода then для вывода сообщений💬 об ошибке🙅‍♂️.

Синтаксис📖 метода catch:

let promise = new Promise((resolve, reject) => {
setTimeout(() => reject(new Error('Ошибка!')), 1000)
})

promise.catch(alert) // выведет "Error: Ошибка!" спустя одну секунду

promise.all​

Этот метод берет массив промисов и возвращает🔄 🆕 новый промис, который будет выполненным, когда все промисы внутри массива выполнены или отклонен, как только встречается промис, который отклоняется.

Например:

const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise1 выполнен')
}, 2000)
})
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Promise2 выполнен')
}, 1500)
})
Promise.all([promise1, promise2])
.then(data => console.log(data[0], data[1]))
.catch(error => console.log(error))

Здесь аргументом внутри then() выступает массив, который содержит значения промисов в том же порядке, в котором они передавались в Promise.all().

Проблемы?​

Пишите в Discord или телеграмм чат, а также подписывайтесь на наши новости

Вопросы:​

Как называется метод который вызывается при успешном выполнении промиса?

  1. reject
  2. resolve

Каким методом можно проверить выполнение всех промисов в массиве?

  1. promise. all
  2. promise.race

Какой метод служит для отлова ошибок в промисах?

  1. then
  2. catch

Для того чтобы понять, на сколько вы усвоили этот урок, пройдите тест в мобильном приложении нашей школы по этой теме или в нашем телеграм боте.

Ссылки:​

  1. MDN web docs
  2. Learn JavaScript
  3. Understanding Promises

Contributors ✨​

Thanks goes to these wonderful people (emoji key):


Philipp Dvinyaninov
📖

Dmitriy Vasilev
💵

Resoner2005
🐛 🎨 🖋

Navernoss
🖋 🐛 🎨

Почему .then() работает без промисов в JavaScript?

Метод then() возвращает обещание. См. документы.

Промис имеет метод обработчика. Как только обещание выполнено или отклонено, соответствующая функция-обработчик будет вызываться асинхронно. Поведение функции обработчика следует определенному набору правил, как указано здесь.

Давайте рассмотрим их один за другим. Вот код, который мы будем проверять бок о бок. Ничего особенного, просто цепочка обещаний, возвращающих значения.

 пусть последовательность = новое обещание (функция (разрешить) {
  console.log('Назовите 1')
  решить(1)
})
последовательность
  .тог(() => {
    console.log('Скажи 2')
    вернуть 2
  })
  .тог(() => {
    console.log('Произнесите 3')
  })
  .тог(() => {
    console.log('Скажи 4')
    вернуть Promise.resolve(4)
  })
  .тог(() => {
    вернуть новое обещание (функция (разрешить) {
      console.log('Произнесите 5')
      setTimeout(() =>
{разрешить(5)}, 1000) }) })
  1. возвращает значение, обещание, возвращенное к этому времени, разрешается с возвращенным значением в качестве его значения;

В коде это Скажем 2 и ваш первоначальный вопрос. Когда значение возвращается, then() возвращает обещание, которое разрешается с возвращенным вами значением.

  1. ничего не возвращает, обещание, возвращенное к тому времени, разрешается с неопределенным значением;

то же, что и выше.

  1. выдает ошибку, обещание, возвращенное к тому времени, отклоняется с выброшенной ошибкой в ​​качестве значения;

то же, что и выше, за исключением того, что теперь then() возвращает обещание, которое отклонено с вашей ошибкой.

  1. возвращает уже разрешенное обещание, обещание, возвращенное к тому времени, разрешается со значением этого обещания в качестве значения;

В коде это Скажем 4 , где обещание уже разрешено. Итак, теперь then() возвращает обещание, которое разрешается со значением 4.

  1. возвращает уже отклоненное обещание, обещание, возвращенное к тому времени, отклоняется со значением этого обещания в качестве значения;

То же, что и выше, за исключением того, что теперь он отклоняется.

  1. возвращает другой ожидающий объект обещания, разрешение/отклонение обещания, возвращенного к этому времени, будет после разрешения/отклонения обещания, возвращенного обработчиком. Кроме того, значение обещания, возвращаемое к тому времени, будет таким же, как значение обещания, возвращаемое обработчиком.

В коде это Скажем 5

. Если вы вернете обещание, которое еще не было разрешено, then() вернет Promise с результатами вашего обещания, т. е. 5.

Следует отметить одну вещь, которую я также недавно узнал (предложено @Bergi в комментариях), что метод then() всегда создает и возвращает новое обещание еще до того, как обратные вызовы цепочки начали выполняться. Обратные вызовы, которые вы передаете , then() просто сообщают обещанию значение/ошибку, с которой обещание должно разрешить/отклонить.

Итак, вот почему 9Цепочка 0019 then() работает, даже если вы специально не возвращаете новое обещание, потому что метод then() всегда создает новое обещание за кулисами и отклоняет/разрешает это обещание с возвращенным вами значением.

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

javascript — путают с .then() в промисах

Задавать вопрос

спросил

Изменено 2 года, 5 месяцев назад

Просмотрено 156 раз

Я новичок в js и изучаю промисы. Я придумал этот код, который будет печатать разрешенные значения из каждой функции и вызывать новые функции, используя .then

функция входа() {
    вернуть новое обещание ((разрешить, отклонить) => {
        setTimeout(() => {
            разрешить ({имя пользователя: 'по умолчанию'})
        }, 1000)
    })
}
функция getVideos () {
    вернуть новое обещание ((разрешить, отклонить) => {
        setTimeout(() => {
            разрешить (['vid1', 'vid2'])
        },1000)
    })
}
функция getDesc() {
    вернуть новое обещание ((разрешить, отклонить) => {
        setTimeout(() => {
            разрешить ('описание')
        }, 1000)
    })
}
постоянный тест = логин ()
test. then (рез => {
    console.log(разрешение)
    получитьвидео()
})
.тог(рес => {
    console.log(разрешение)
    получить описание()
})
.затем(рез => console.log(рез))
 

Но я не получаю ожидаемого результата, я думал, что все операторы в .then() должны быть выполнены и разрешены для перехода к следующему оператору .then() . Но очевидно, что это не тот случай, поскольку я получаю в качестве вывода следующее:

 {имя пользователя: 'по умолчанию'}
неопределенный
неопределенный
 

Но я ожидал, что вывод будет похож на этот —

 {имя пользователя: 'по умолчанию}
['вид1', 'вид2']
описание
 

, пожалуйста, укажите, где я ошибаюсь. Любая помощь приветствуется, большое спасибо

  • javascript
  • асинхронный
  • обещание
  • разрешение

0

Вам нужно добавить return внутрь ваших цепочек, когда вы вызываете эти функции. Например:

 функция логин() {
    вернуть новое обещание ((разрешить, отклонить) => {
        setTimeout(() => {
            разрешить ({имя пользователя: 'по умолчанию'})
        }, 1000)
    })
}
функция getVideos () {
    вернуть новое обещание ((разрешить, отклонить) => {
        setTimeout(() => {
            разрешить (['vid1', 'vid2'])
        },1000)
    })
}
функция getDesc() {
    вернуть новое обещание ((разрешить, отклонить) => {
        setTimeout(() => {
            разрешить ('описание')
        }, 1000)
    })
}
постоянный тест = логин ()
test.then (рез => {
    console.log(разрешение)
    вернуть getVideos ()
})
.тог(рес => {
    console.log(разрешение)
    вернуть getDesc()
})
.затем(рез => console.log(рез))
 

Это хорошее руководство: https://javascript.info/promise-chaining

3

Внесите несколько незначительных изменений:

 const test = login()
test.then (рез => {
 console.