Ранее мы рассмотрели, как из функции промиса мы можем передать во вне результат асинхронной операции:
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);})