Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
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, необходимо изучить теорию и приступать к практике. Стоит практиковать задачи в различных вариациях: расширять задачи, изменять существующие примеры и отслеживать изменения.
На этом всё. И да прибудет с нами сила!