Ранее мы рассмотрели, как из функции промиса мы можем передать во вне результат асинхронной операции:
const myPromise = new Promise(function(resolve){ console.log("Выполнение асинхронной операции"); resolve("Привет мир!"); });
Теперь получим это значение. Для получения результата операции промиса применяется функция then() объекта Promise
:
then(onFulfilled, onRejected);
Первый параметр функции - onFulfilled
представляет функцию, которая выполняется при успешном завершении промиса и в качестве параметра получает переданные в resolve()
данные.
Второй параметр функции - onRejected
представляет функцию, которая выполняется при возникновении ошибки и в качестве параметра
получает переданные в reject()
данные.
Функция then() возвращает также объект Promise
.
Так, получим переданные данные:
const myPromise = new Promise(function(resolve){ console.log("Выполнение асинхронной операции"); resolve("Привет мир!"); }); myPromise.then(function(value){ console.log(`Из промиса получены данные: ${value}`); })
То есть параметр value
здесь будет представлять строку "Привет мир!"
, которая передается в resolve("Привет мир!")
.
В итоге консольный вывод будет выглядеть следующим образом:
Выполнение асинхронной операции Из промиса получены данные: Привет мир!
Для примера вызове несколько промисов, чтобы увидеть асинхронность в деле:
const myPromise3000 = new Promise(function(resolve){ console.log("[myPromise3000] Выполнение асинхронной операции"); setTimeout(()=>{resolve("[myPromise3000] Привет мир!")}, 3000); }); const myPromise1000 = new Promise(function(resolve){ console.log("[myPromise1000] Выполнение асинхронной операции"); setTimeout(()=>{resolve("[myPromise1000] Привет мир!")}, 1000); }); const myPromise2000 = new Promise(function(resolve){ console.log("[myPromise2000] Выполнение асинхронной операции"); setTimeout(()=>{resolve("[myPromise2000] Привет мир!")}, 2000); }); myPromise3000.then((value)=>console.log(value)); myPromise1000.then((value)=>console.log(value)); myPromise2000.then((value)=>console.log(value));
Здесь определены три однотипных промиса. Чтобы каждый из них не выполнялся сразу, они используют функцию setTimeout и устанавливают возвращаемое значение только через несколько секунд. Для разных промисов длительность задержки различается. И в данном случае мы получим следующий консольный вывод:
[myPromise3000] Выполнение асинхронной операции [myPromise1000] Выполнение асинхронной операции [myPromise2000] Выполнение асинхронной операции [myPromise1000] Привет мир! [myPromise2000] Привет мир! [myPromise3000] Привет мир!
Здесь мы видим, что первым начал выполняться промис myPromise3000, однако он же завершился последним, так как для него установлено наибольшее время задержки - 3 секунды. Однако его задержка не помешала выполнению остальных промисов.
При этом нам необязательно вообще передавать в resolve()
какое-либо значение. Возможно, асинхронная операция просто выполняется и передает во вне никакого результата.
const x = 4; const y = 8; const myPromise = new Promise(function(){ console.log("Выполнение асинхронной операции"); const z = x + y; console.log(`Результат операции: ${z}`) }); myPromise.then();
В данном случае функция в промисе вычисляет сумму чисел x и y и выводит результат на консоль.
Иногда требуется просто вернуть из промиса некоторое значение. Для этого можно использовать метод Promise.resolve(). В этот метод передается возвращаемое из промиса значение. Метод Promise.resolve() возвращает объект Promise:
const myPromise = Promise.resolve("Привет мир!"); myPromise.then(value => console.log(value)); // Привет мир!
Нередко промис определяется через функцию, которая возвращет объект Promise. Например:
function sum(x, y){ return new Promise(function(resolve){ const result = x + y; resolve(result); }) } sum(3, 5).then(function(value){ console.log("Результат операции:", value);}); sum(25, 4).then(function(value){ console.log("Сумма чисел:", value);});
Здесь функция sum()
принимает два числа и возвращает промис, который инкапсулирует операцию сумму этих чисел. После вычисления сумма чисел передается в
resolve()
, соответственно мы ее затем можем получить через метод then()
. Определение промиса через функцию позволяет нам, с одной стороны, при вызове функции
передавать разные значения. А с другой стороны, работать с результатом этой функции как с промисом и настроить при каждом конкретном вызове обработку полученного
значения.
Результат работы программы:
Результат операции: 8 Сумма чисел: 29
Однако, что если у нас совпадает принцип обработки полученного из асинхронной функции значения?
sum(3, 5).then(function(value){ console.log("Результат операции:", value);}); sum(25, 4).then(function(value){ console.log("Результат операции:", value);});
В этом случае логика обработки будет повторяться. Но поскольку метод then()
также возвращает объект Promise, то мы можем сделать следующим образом:
function sum(x, y){ return new Promise(function(resolve){ const result = x + y; resolve(result); }).then(function(value){ console.log("Результат операции:", value);}); } sum(3, 5); sum(25, 4);
А что, если мы хотим, чтобы у программиста был выбор: если он хочет, то может определить свой обработчик, а если нет, то применяется некоторый обработчик по умолчанию. В этом случае мы можем определить функцию обработчика в качестве параметра функции, а если он не передан, то устанавливать обработчик по умолчанию:
function sum(x, y, func){ // если обработчик не установлен, то устанавливаем обработчик по умолчанию if(func===undefined) func = function(value){ console.log("Результат операции:", value);}; return new Promise(function(resolve){ const result = x + y; resolve(result); }).then(func); } sum(3, 5); sum(25, 4, function(value){ console.log("Сумма:", value);});
Здесь при первом вызове функции sum()
(sum(3, 5)
) будет срабатывать обработчик по умолчанию. Во втором случае обработчик явным
образом передается через третий параметр, соответственно он будет задействован sum(25, 4, function(value){ console.log("Сумма:", value);})