Введение в промисы в JavaScript
Вы уже знаете, что использование коллбэк-модели асинхронности легко приводит к ситуации callback hell. Поэтому в JavaScript была введена новая модель под названием промисы (англ. promise, обещание). Давайте изучим эту модель.
Промис представляет собой объект, в который параметром передается функция, внутри которой нужно размещать наш асинхронный код:
let promise = new Promise(function() {
// асинхронный код
});
Как вы видите, я записал объект с промисом
в переменную promise. В каком-то другом
месте кода я могу применить к этой переменной
метод then, передав в него функцию
с кодом, который должен быть выполнен по
завершении асинхронного кода, написанного
при создании данного промиса:
promise.then(function() {
// выполнится при завершении асинхронного кода
});
Звучит запутано, поэтому давайте посмотрим на примере. Пусть у меня есть вот такой асинхронный код:
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
}, 3000);
Пусть я хочу решить для него нашу основную
задачу асинхронности: выполнить некоторый
код после срабатывания таймера. При этом
я не хочу размещать этот код в самом таймере
и хочу, чтобы в этот код как-то попал результат,
написанный мною в переменной result.
В общем-то, мы решали эту задачу в предыдущих
уроках через коллбэки и подписки. Давайте
теперь посмотрим, как это сделать через промисы.
Для начала нужно обернуть наш асинхронный код в промис:
let promise = new Promise(function() {
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
}, 3000);
});
Этого, однако, не достаточно. Мы должны в явном виде указать, что наш асинхронный код завершился. В этом нам поможет специальная функция завершения, автоматически попадающая в первый параметр функции, если он указан:
let promise = new Promise(function(resolve) { // указываем параметр
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
}, 3000);
});
С помощью функции завершения мы можем явно указать промису, что асинхронный код завершился. Для этого мы должны вызвать эту функцию в нужном нам месте:
let promise = new Promise(function(resolve) {
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
resolve(); // завершаем промис
}, 3000);
});
При этом, если мы хотим передать вовне какой-то результат асинхронного кода, мы можем передать его параметром нашей функции завершения:
let promise = new Promise(function(resolve) {
setTimeout(function() {
let result = [1, 2, 3, 4, 5];
resolve(result); // передаем результат
}, 3000);
});
Можно, конечно же, избавится от промежуточной переменной:
let promise = new Promise(function(resolve) {
setTimeout(function() {
resolve([1, 2, 3, 4, 5]);
}, 3000);
});
Теперь в любом другом месте мы можем вызвать
метод then нашего промиса:
promise.then(function() {
// сработает по завершению промиса
});
Результат работы промиса попадет в первый параметр функции, если мы пожелаем его указать:
promise.then(function(result) {
console.log(result); // выведет массив с результатом
});
Сделайте промис, внутри которого будет задержка
в 5 секунд, после которой промис должен
выполнится, своим результатом вернув какой-нибудь
текст. Выведите этот текст на экран.