#9 ES6 promises

poster
В этом уроке мы разберем, что такое es6 promises и как они работают. Научимся применять resolve и reject и подписываться на получение данных с помощью then и catch.
Понравилось? Поделитесь с друзьями!
Понравилось?
Поделитесь с друзьями!
Комментарии
Текст видео

В этом уроке мы с вами разберем как работают es6 promises.

Зачем вообще придумали promises? Если какая-то операция выполняется долго, то есть асинхронно, то ее нельзя просто написать с помощью синхронного кода в javascript. Поэтому для этого и используют промисы. По русски promises переводятся, как обещания. Самые частые примеры промисов это setTimeout, получение данных с сервера, запись в файл и другие.

Итак как же выглядит промис?

const promise = new Promise()

Это минимальная запись промиса. Мы просто создаем новый екземпляр класса Promise. В качестве аргумента мы можем передать функцию с параметрами resolve и reject.

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

})

Resolve и reject - это тоже функции. Мы вызываем resolve внутри, когда говорим, что промис завершился успешно, а reject, когда мы хотим сказать, что случилось что-то неожиданное, например ошибка.

Давай напишем условие, в котором вызовем функцию resolve с агрументом hello world. В else вызовем reject.

const promise = new Promise((resolve, reject) => {
  if (true) {
    resolve('hello world')
  } else {
    reject()
  }
})

Как вы понимаете у нас всегда вызывается resolve.

Теперь нам нужно как то подписаться на то, что произошло внутри промиса. Для этого мы будем использовать then и catch. Then будет вызыватся на resolve, а catch на reject.

Давайте добавим два обработчика

promise.then(data => console.log('success: ', data))
promise.catch(error => console.log('error: ', error))

В каждый из них мы передали callback, в первом первым аргументом идут данные, которые мы передали в resolve, а в error ошибка

Если мы посмотрим в браузер, то у нас вывелось

success: hello world

Если мы исправим true на false в условии, то увидим, что у нас вывалился error

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

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (true) {
      resolve('hello world')
    } else {
      reject()
    }
  }, 2000)

})

promise.then(data => console.log('success: ', data))
promise.catch(error => console.log('error: ', error))

Если мы посмотрим в браузер, то видно, что надпись success выводится только через 2 секунды, так как с setTimeout код у нас выполняется асинхронно

Итак еще раз по коду:

  1. Мы создали новый промис
  2. Внутри него делаем асинхронную операцию (В нашем случае setTimeout)
  3. Вызываем resolve, когда код выполнился успешно
  4. Вызываем reject, если произошла ошибка
  5. С помощью then и catch обрабатываем результат выполнения промиса

Promise then и catch можно писать цепочкой, так как then возвращает все тот же промис.

promise.then(data => console.log('success: ', data))
  .catch(error => console.log('error: ', error))

Это очень часто применяющаяся практика, чтобы не дублировать код

Еще одна частая практика это цепочки then. Мы можем писать их сколько угодно раз, и они будут выполнятся по очереди.

promise.then(data => console.log('success: ', data))
  .then(data => console.log('success 2: ', data))
  .catch(error => console.log('error: ', error))

Если мы посмотрим в браузер, то второй then выполнился после первого. Единственный нюанс в том, что data в второй then undefined. Это потому, что каждый следующий then вызывается с данными которые были возвращены в предыдущем.

promise.then(data => {
  console.log('success: ', data)
  return 'foo bar'
})
  .then(data => console.log('success 2: ', data))
  .catch(error => console.log('error: ', error))

Еще один нюанс. Мы можем не использовать catch, а в then передать функцию вторым аргументом. Она сработает так же как catch

promise.then(
  data => console.log('success: ', data),
  error => console.log('error: ', error)
)

Но я предпочитаю использовать catch, так как это более наглядно.

И последнее. Любой throw, который попадется в коде моментально выбросит нас в catch

const promise = new Promise((resolve, reject) => {
  throw new Error('ALARM')
  setTimeout(() => {
    if (true) {
      resolve('hello world')
    } else {
      reject()
    }
  }, 2000)

})

Итак в этом уроке мы разобрали что такое es6 promises и как они работают. Применяли resolve и reject и подписывались на асинхронное получение данных с помощью then и catch.

Если у вас возникли какие-то вопросы или комментарии, пишите их прямо под этим видео.

Только зарегистрированные пользователи могут оставлять комментарии.  Войдите, пожалуйста.
Igor-OK
9 месяцев назад
Спасибо! очень круто объясняешь. Талант от бога!
monsterlessons
9 месяцев назад
Спасибо, очень приятно
Alexandr Taldykin
12 месяцев назад
Немного не понял. Попытался написать промис: var ourData; var promise = new Promise(function(resolve, reject) { UsersModel.find({userName:'Jack'}, function (err,userMongo) { userMongo.forEach(function (one) { resolve({ username: one.userName, password: one.password }); }); }); }); promise.then(function(data){ return data; }); В итоге промис резолвится, в then он выводится в консоль. Но вот вопрос. Как глобальной переменной ourData, которая объявлена в начале, присвоить данные, которые возвращает then. ourData Undefined, несколько часов просидел, безрезультатно :)
monsterlessons
12 месяцев назад
Например так promise.then(function(data){ ourData = data });
Alexandr Taldykin
12 месяцев назад
Спасибо за ответ. А если внутри promise.then() находится именнованная функция... Как можно обратиться к этой функции чтобы она была доступна другим внешним функциям? Например, как присвоить module.exports = функция которая в promise.then ?
monsterlessons
12 месяцев назад
Никак. Это нарушения правил javascript. Вы не можете получить доступ к внутренней функции, если она каким то образом не присвоена к переменной снаружи. Обычно из модуля экспортируют функцию, которая возвращает промис. И везде просто используют эту функцию.
александр устинов
1год назад назад
Подскажите, как добавить разные промисы then на разные resolv'ы ?
monsterlessons
1год назад назад
Не совсем понял, что вы имеете ввиду. Можете с примером кода написать?
александр устинов
1год назад назад
Допустим есть функция, которая возвращает код загрузки страницы. Можно ли написать, чтобы при resolve 200 вызывался then с console.log(), при 201 - then с alert , а на reject 404 catch с console.log. Т.е. чтобы в разных случаях вызывался разный then
monsterlessons
1год назад назад
Нет, поскольку then значит success и из них вы можете только строить цепочки. loadPage().then(result => { if (result.statusCode === 200) { console.log('200') } else if (result.statusCode === 201) { console.log('201') } }) .catch(err => console.log(err)) Только так
александр устинов
1год назад назад
Спасибо большое. Именно это и спрашивал)
Саша Медленный
1год назад назад
Сенсей, научи async/await!
monsterlessons
1год назад назад
Спасибо за идею. Добавил в список будущих видео.
Rustam Apaev
1год назад назад
Поддерживаю! Тоже актуально, а я уже привык все знания с этого сайта черпать)
monsterlessons
1год назад назад
Знаний слишком много, чтобы успевать по всем ним видео записывать))
Максим Маркелов
2 лет назад
Все очень круто. Очень доходчиво и понятно. У меня вопрос будет ли продолжение и если да, то планируется ли урок по генераторам и итераторам??
monsterlessons
2 лет назад
Спасибо. Пока не планировалось, так как генераторы и итераторы намного более редко используемая тема, чем те, что были рассказаны. Если много людей напишет, что такие уроки нужны, то я их сниму.