В этом уроке мы с вами разберем как работают 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 код у нас выполняется асинхронно
Итак еще раз по коду:
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.
Если у вас возникли какие-то вопросы или комментарии, пишите их прямо под этим видео.