Promises

Промисы — это полезные объекты, которые помогают с асинхронными задачами. Они помогают избежать callback hell. Выдают значения тогда, когда они уже выполнились или не выполнились.

let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Hello");
  }, 1500);
});

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

И теперь, чтобы воспользоваться промисом, нужно воспользоваться методом then

promise.then();

then означает, что когда промис зарезолвлен, сделать то что мы укажем в качестве аргумента в then. В then мы также передаем функцию, которая принимает в качетсве аргумента то, что мы зарезолвили в промисе.

promise.then(value => console.log(value));

А как быть если произошла ошибка в промисе?

let promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    if (false) resolve("Hello");
    if (true) reject("Buy");
  }, 1500);
});

promise.then(
  value => {
    console.log(value); // всё гуд
  },
  error => {
    console.log(error); // усё гауно
  }
);

Мы просто передаем вторую функцию в then, которая отвечает за reject.

Цепочки промисов (promise chaining)

function waitASecond(seconds) {
  return new Promise((res, rej) => {
    setTimeout(() => {
      seconds++;
      resolve(seconds);
    }, 1000);
  });
}

waitASecond(0)
  .then(waitASecond)
  .then(seconds => {
    console.log(seconds);
  });

Поимка ошибок

function waitASecond(seconds) {
  return new Promise((res, rej) => {
    if (seconds > 2) {
      rej("REJECTED");
    } else {
      setTimeout(() => {
        seconds++;
        res(seconds);
      }, 1000);
    }
  });
}

waitASecond(3)
  .then(waitASecond)
  .then(seconds => {
    console.log(seconds);
  })
  .catch(err => {
    console.log(err);
  });

В этом примере мы сразу получим REJECTED, так как сработает условие что входной параметр больше чем нужно.

Блок catch срабатывает каждый раз, когда мы получаем reject.

Методы All и Race

Также ES6 предлагает 2 метода, которые можно использовать, чтобы собирать промисы.

let promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('RESOLVED');
    }, 1000);
});

let promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject('REJECTED');
    }, 2000);
});

Promise.all([promise1, promise2])
.then(success => console.log(success))
.catch(err => console.log(err));

Рассмотрим встроенный в промисы метод all. Он принимает массив из промисов. Т.е. мы собираем промисы в один единственный. После чего мы опять используем метод then, который получает данные с промисов. Но имейте в виду, при объединении промисов таким образом, если в одном из промисов вылетает ошибка то весь блок вылетает в реджект.

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

Также есть метод race. Его отличие от all в том, что race возвращает первый сделанный промис в массиве. Если первый промис будет зареджектен, то все промисы пролетят как фанера над Парижем.