Obținerea rezultatului operației într-un Promise
Anterior, am examinat cum putem transmite rezultatul unei operațiuni asincrone dintr-o funcție promise:
const myPromise = new Promise(function(resolve){
console.log("Executarea operațiunii asincrone");
resolve("Salut lume!");
});
Acum să obținem această valoare. Pentru a obține rezultatul operației unui promise se utilizează funcția then() a obiectului Promise:
then(onFulfilled, onRejected);
Primul parametru al funcției - onFulfilled reprezintă funcția care se execută la finalizarea cu succes a promise-ului și primește ca parametru datele transmise în resolve().
Al doilea parametru al funcției - onRejected reprezintă funcția care se execută la apariția unei erori și primește ca parametru datele transmise în reject().
Funcția then() returnează de asemenea un obiect Promise.
Astfel, obținem datele transmise:
const myPromise = new Promise(function(resolve){
console.log("Executarea operațiunii asincrone");
resolve("Salut lume!");
});
myPromise.then(function(value){
console.log(`Date obținute din promise: ${value}`);
})
Adică, parametrul value aici va reprezenta șirul "Salut lume!", care este transmis în resolve("Salut lume!"). În final, ieșirea în consolă va arăta astfel:
Executarea operațiunii asincrone
Date obținute din promise: Salut lume!
Pentru exemplu, să apelăm mai multe promise-uri, pentru a vedea asincronitatea în acțiune:
const myPromise3000 = new Promise(function(resolve){
console.log("[myPromise3000] Executarea operațiunii asincrone");
setTimeout(()=>{resolve("[myPromise3000] Salut lume!")}, 3000);
});
const myPromise1000 = new Promise(function(resolve){
console.log("[myPromise1000] Executarea operațiunii asincrone");
setTimeout(()=>{resolve("[myPromise1000] Salut lume!")}, 1000);
});
const myPromise2000 = new Promise(function(resolve){
console.log("[myPromise2000] Executarea operațiunii asincrone");
setTimeout(()=>{resolve("[myPromise2000] Salut lume!")}, 2000);
});
myPromise3000.then((value)=>console.log(value));
myPromise1000.then((value)=>console.log(value));
myPromise2000.then((value)=>console.log(value));
Aici sunt definite trei promise-uri identice. Pentru ca fiecare dintre ele să nu se execute imediat, folosesc funcția setTimeout și stabilesc valoarea returnată doar după câteva secunde. Durata întârzierii variază pentru diferite promise-uri. Și în acest caz vom obține următoarea ieșire în consolă:
[myPromise3000] Executarea operațiunii asincrone
[myPromise1000] Executarea operațiunii asincrone
[myPromise2000] Executarea operațiunii asincrone
[myPromise1000] Salut lume!
[myPromise2000] Salut lume!
[myPromise3000] Salut lume!
Aici vedem că primul a început să se execute promise-ul myPromise3000, dar el s-a și terminat ultimul, deoarece pentru el este stabilit cel mai lung timp de întârziere - 3 secunde. Totuși, întârzierea sa nu a împiedicat executarea celorlalte promise-uri.
În același timp, nu este necesar să transmitem în resolve() nicio valoare. Poate operațiunea asincronă se execută pur și simplu și nu transmite niciun rezultat în exterior.
const x = 4;
const y = 8;
const myPromise = new Promise(function(){
console.log("Executarea operațiunii asincrone");
const z = x + y;
console.log(`Rezultatul operațiunii: ${z}`)
});
myPromise.then();
În acest caz, funcția din promise calculează suma numerelor x și y și afișează rezultatul în consolă.
Metoda Promise.resolve
Uneori este necesar să returnăm pur și simplu dintr-un promise o anumită valoare. Pentru aceasta se poate folosi metoda Promise.resolve(). În această metodă se transmite valoarea returnată din promise. Metoda Promise.resolve() returnează un obiect Promise:
const myPromise = Promise.resolve("Salut lume!");
myPromise.then(value => console.log(value)); // Salut lume!
Definirea unui promise prin intermediul unei funcții
Adesea, un promise este definit printr-o funcție care returnează un obiect Promise. De exemplu:
function sum(x, y){
return new Promise(function(resolve){
const result = x + y;
resolve(result);
})
}
sum(3, 5).then(function(value){ console.log("Rezultatul operațiunii:", value);});
sum(25, 4).then(function(value){ console.log("Suma numerelor:", value);});
Aici, funcția sum() acceptă două numere și returnează un promise care încapsulează operația de adunare a acestor numere. După calcularea sumei, aceasta este transmisă în resolve(), astfel încât ulterior o putem obține prin metoda then(). Definirea unui promise printr-o funcție ne permite, pe de o parte, să transmitem diferite valori la apelul funcției. Iar pe de altă parte, să lucrăm cu rezultatul acestei funcții ca și cum ar fi un promise și să configurăm la fiecare apel concret procesarea valorii obținute.
Rezultatul execuției programului:
Rezultatul operațiunii: 8
Suma numerelor: 29
Totuși, ce se întâmplă dacă avem același principiu de procesare a valorii obținute dintr-o funcție asincronă?
sum(3, 5).then(function(value){ console.log("Rezultatul operațiunii:", value);});
sum(25, 4).then(function(value){ console.log("Rezultatul operațiunii:", value);});
În acest caz, logica de procesare se va repeta. Dar, deoarece metoda then() returnează de asemenea un obiect Promise, putem proceda în felul următor:
function sum(x, y){
return new Promise(function(resolve){
const result = x + y;
resolve(result);
}).then(function(value){ console.log("Rezultatul operațiunii:", value);});
}
sum(3, 5);
sum(25, 4);
Configurare flexibilă a funcției
Și ce se întâmplă dacă dorim ca programatorul să aibă posibilitatea de alegere: dacă dorește, poate să definească propriul handler, iar dacă nu, se aplică un handler implicit. În acest caz, putem defini funcția handler ca parametru al funcției, iar dacă nu este transmis, să stabilim handlerul implicit:
function sum(x, y, func){
// dacă handlerul nu este stabilit, atunci stabilim handlerul implicit
if(func===undefined) func = function(value){ console.log("Rezultatul operațiunii:", value);};
return new Promise(function(resolve){
const result = x + y;
resolve(result);
}).then(func);
}
sum(3, 5);
sum(25, 4, function(value){ console.log("Suma:", value);});
Aici, la prima apelare a funcției sum() (sum(3, 5)), va acționa handlerul implicit. În al doilea caz, handlerul este transmis explicit prin al treilea parametru, respectiv el va fi utilizat sum(25, 4, function(value){ console.log("Suma:", value);}).