Базовые задачи на Promise в JavaScript

Kate

Administrator
Команда форума
Promise - специальный объект, который хранит своё состояние и используется для обработки результатов асинхронных операций.

Что будет в статье:

  • Основные задачи на Promsie, которые часто спрашивают на собеседованиях
  • Код задач с подробными комментариями
Чего в статье НЕ будет:

  • Теории про Promsie и Event Loop
  • Задач на Event Loop, показывающих приоритетность выполнения Promise, setTimeout и т.д.
Статья предназначена для тех, кто уже изучил теорию по Promise и хочет попрактиковаться в решении тестовых задач.

Основные методы Promise​

Приведу список методов, которые будут использоваться а задачах:

  • "Promise.resolve(value)" - создаёт успешно выполнившийся Promise с результатом value
  • "Promise.reject(value)" - создаёт выполнившийся Promise с ошибкой
  • ".then" - обработчик событий Promise "onFulfilled" и "onRejected"
  • ".catch" - обработчик события Promise "onRejected"
  • ".finally" - дает возможность запустить один раз определенный участок кода, который должен выполниться вне зависимости от того, с каким результатом выполнился Promise

Задачи на .then​

1. Случаи, когда .then возвращает или не возвращает значение​

Promise.resolve("1")
// Promise.resolve вернул "1"
.then(data => {
console.log(data); // => "1"
})

// .then ничего не вернул
.then(data => {
console.log(data); // => "undefined"
return "2";
})

// .then вернул "2"
.then(data => {
console.log(data); // => "2"
})

2. Второй аргумент .then​

  • Первая задача
Promise.reject(1)
// skip
// обработать reject можно только в .catch
.then(data => {
console.log(data);
})

// второй аргумент .then вместо .catch
.then(null, data => console.log(data)) // => 1

// после обработки ошибки попадаем в .then
// => "ok"
.then(() => console.log('ok'));
  • Вторая задача
Promise.reject()
// используем колбэки для .then и для .catch
.then(
data => console.log('ok'), // => skip
data => console.log('error') // => "error"
)

3. null в .then​

Promise.resolve("1")
// skip
.then(null)

// придут данные из Promise.resolve
.then(data => console.log(data)) // => "1"

Задачи на .catch​

1. Ошибка из Promise.reject​

Promise.reject("Api Error")
// skip из-за Promise.reject
.then(data => console.log('ok'))

// обработка ошибки
.catch(error => {
console.log(error); // => "Api Error"
return "1";
})

// catch вернул "1"
.then(data => {
console.log(data); // => "1"
})

2. Ошибка из Promise.reject в .catch​

Promise.reject()
// обработка Promise.reject
.catch(() => {
console.log('error1'); // => "error1"
return Promise.reject();
// аналогично
// return reject();
})

// обработка Promise.reject из предыдущего .catch
.catch(() => {
console.log('error2'); // => "error2"
})

3. Ошибка throw new Error​

Promise.resolve()
.then(data => {
// возникновение ошибки
throw new Error('Api Error');
// не имеет значения, что вернули
return 1;
})

// skip, потому что предыдущий .then бросил ошибку
.then(data => console.log('ok'))

// обработка ошибки
.catch(error => {
console.log(error.message); // => "Api Error"
return "2";
})

// .catch вернул "2"
.then(data => {
console.log(data); // => "2"
})

4. Необработанная ошибка в Promise​

  • Необработанная ошибка в Promise не влияет на работу программы, т.к. Promise не выпускает ошибку за свои пределы.
Promise.resolve()
.then(() => {
throw new Error('Api Error');
})

// код будет работать
setTimeout(() => {
console.log('setTimeout'); // => "setTimeout"
}, 1000);

5. null в .catch​

Promise.reject("Api Error")
// skip: ошибку не обработали
.catch(null)

// skip из-за необработанной ошибки
.then(data => console.log('ok'))

// обработка ошибки
.catch(error => console.log(error)) // => "Api Error"

// .then выполнится
.then(data => console.log('ok')) // => "ok"

Задачи на .finally​

  • Первая задача
Promise.resolve()
.then(() => {
return "1";
})

// .then вернул "1", но .finally пропустит его мимо себя
.finally(data => {
console.log(data); // => "undefined"
return "2";
})

// из .finally вернули "2", но результат берется из предыдущего .then или .catch
.then(data => console.log(data)) // => "1"
  • Вторая задача
Promise.reject()
// .finally выполняется в любом случае: даже при возникновении ошибки
.finally(data => {
console.log('finally'); // => "finally"
})

Задачи на несколько Promise​

  • Если несколько Promise, то ".then" будет выполняться последовательно для каждого:
Promise.resolve()
.then(() => console.log(1)) // "Первый"
.then(() => console.log(2)) // "Третий"

Promise.resolve()
.then(() => console.log(11)) // "Второй"
.then(() => console.log(12)) // "Четвертый"
  • При ".catch" аналогично:
Promise.resolve()
.then(() => console.log(1)) // "Первый"
.then(() => { console.log(2); throw new Error(); }) // "Третий"
.catch(() => console.log(3)) // "Пятый"
.then(() => console.log(4)) // "Седьмой"

Promise.resolve()
.then(() => console.log(11)) // "Второй"
.then(() => { console.log(12); throw new Error(); }) // "Четвертый"
.catch(() => console.log(13)) // "Шестой"
.then(() => console.log(14)) // "Восьмой"

Задача на бесконечные микротаски​

В качестве бонуса покажу, как повесить браузер микротасками, которыми являются Promise:

const foo = () => {
Promise.resolve().then(() => foo())
}

foo();

Заключение​

В статье я собрал базовые задачи с собеседований. Чтобы понять Promise, необходимо изучить теорию и приступать к практике. Стоит практиковать задачи в различных вариациях: расширять задачи, изменять существующие примеры и отслеживать изменения.

На этом всё. И да прибудет с нами сила!

 
Сверху