Я просто никак не могу понять их смысла. Зачем мне писать промисы (promise) или создавать функции через async/await если я могу просто поставить setTimeout()?
Ответ Промисы это удобная замена callback'ам Представим что у нас есть функция: const awesomeFunction = () => { // ... делаю дела // ... делаю дела } им мы хотим выполнить другую функцию сразу после того как первая будет завершена: const awesomeFunction = callback => { // ... делаю дела // ... делаю дела callback() } const printFunction = () => { // ... что то вывожу в консоль } awesomeFunction(printFunction) Мы можем переписать ее с использованием промисов, но пока большой разницы это не даст, так как наш код синхронный: const awesomeFunction = () => { return new Promise (resolve => { // ... делаю дела // ... делаю дела resolve() }) } const printFunction = () => { // ... что то вывожу в консоль } awesomeFunction().then(printFunction) Пока ничего особенного, однако обратите внимание насколько понятнее он стал при использовании промисов и метода then(). На примере единственного callback'а это может быть не так и заметно, но при варианте когда их множество это спасет нас от так называемого Callback Hell'a. Если Вы еще не сталкивались с таким термином, то представьте как выглядел бы код с сотней callback'ов, вложенных один в другой. На данный момент: Достаточно понимать что промисы это те же самые callback'и, только с более удобным синтаксисом, которые упрощают написание кода и его поддержку. Рассмотрим те же варианты при асинхронном коде: const awesomeFunction = callback => { // функция printFunction будет // запущена через одну секунду setTimeout(callback, 1000) } const printFunction = () => { // ... что то вывожу в консоль } awesomeFunction(printFunction) Есть ли разница с синхронным вариантом? Для нас ее нет, мы все так же вызываем наш callback именно тогда когда мы посчитали это нужным, в данном конкретном случае спустя одну секунду после начала выполнения функции awesomeFunction. Перепишем на промисы: const awesomeFunction = () => { return new Promise (resolve => setTimeout(resolve, 1000)) } const printFunction = () => { // ... что то вывожу в консоль } awesomeFunction().then(printFunction) Предположим что printFunction тоже асинхронная, тогда мы сможем заchein'ить их одну за другой, поскольку теперь она тоже возвращает нам промис: const awesomeFunction = () => { return new Promise (resolve => setTimeout(resolve, 1000)) } const printFunction = () => { return new Promise (resolve => setTimeout(() => { console.log("printed") resolve() }, 1000)) } const anotherFunction = () => { // ... делаю что нибудь третие } awesomeFunction() .then(printFunction) .then(anotherFunction) Обратите внимание насколько понятнее такая запись типа then then по сравнению с вложенностью callback'ов. Если мы хотим передать что то из одной функции в другую, то мы можем сделать это так: const awesomeFunction = () => { return new Promise (resolve => setTimeout(() => { resolve("текст для \"print\"") }, 1000)) } const printFunction = text => { console.log(text) } awesomeFunction().then(text => printFunction(text))
В версии ECMAScript 2017 появился еще более удобный синтаксис для работы с асинхронностью под названием async/await. Он основан на промисах и по сути не чем от них не отличаться, однако позволяет нам писать асинхронный код почти так же как и синхронный. Для того что бы указать что конкретная функция является асинхронной нам достаточно добавить специальное слово async, а перед асинхронной операцией слово await: const awesomeFunction = () => { return new Promise (resolve => setTimeout(() => { resolve("текст для \"print\"") }, 1000)) } const printFunction = text => { console.log(text) } // что бы не отходить далеко от предидущих примеров // я завернул вызовы в IIFE // что это такое см. ниже (async() => { const text = await awesomeFunction() printFunction(text) })() // если бы мы делали вызовы из другой функции // то это выглядело бы так const parentFunction = async() => { const text = await awesomeFunction() printFunction(text) } parentFunction() Что такое IIFE