MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Async și await

Introducerea standardului ES2017 în JavaScript a adus două noi operatori: async și await, care sunt destinate să simplifice lucrul cu promise-urile.

Operatorul async definește o funcție asincronă, în care se presupune că se vor executa una sau mai multe sarcini asincrone:

async function nume_funcție(){
   // operațiuni asincrone
}

În interiorul unei funcții asincrone putem utiliza operatorul await. Acesta este plasat înaintea apelului unei operațiuni asincrone care returnează un obiect Promise:

async function nume_funcție(){
   
   await operațiune_asincronă();
}

Operatorul await suspendă execuția funcției asincrone până când operațiunea asincronă (obiectul Promise) returnează un rezultat.

Trebuie să ținem cont că operatorul await poate fi utilizat doar în interiorul unei funcții la care se aplică operatorul async.

Să examinăm cel mai simplu exemplu utilizând Promise:

function sum(x, y){
   return new Promise(function(resolve){
       const result = x + y;
       resolve(result);
   });
}
sum(5, 3).then(function(value){
   console.log("Rezultatul operațiunii asincrone:", value);
}); // Rezultatul operațiunii asincrone: 8

În acest caz, funcția sum() reprezintă o sarcină asincronă. Ea primește două numere și returnează un obiect Promise, în care se realizează adunarea acestor numere. Rezultatul adunării este transmis funcției resolve(). Și apoi, în metoda then(), putem obține acest rezultat și să realizăm diferite acțiuni cu acesta.

Acum să rescriem acest exemplu utilizând async/await:

function sum(x, y){
   return new Promise(function(resolve){
       const result = x + y;
       resolve(result);
   });
}
// varianta simplificată
// function sum(x, y){ return Promise.resolve(x + y);}


async function calculate(){
   const value = await sum(5, 3);
   console.log("Rezultatul operațiunii asincrone:", value);
}
calculate();    // Rezultatul operațiunii asincrone: 8

În acest caz, funcția sum() reprezintă o sarcină asincronă. Ea primește două numere și returnează un obiect Promise, în care se realizează adunarea acestor numere. Rezultatul adunării este transmis funcției resolve(). Și apoi, în metoda then(), putem obține acest rezultat și să realizăm diferite acțiuni cu acesta.

Acum să rescriem acest exemplu utilizând async/await:

function sum(x, y){
   return new Promise(function(resolve){
       const result = x + y;
       resolve(result);
   });
}
// varianta simplificată
// function sum(x, y){ return Promise.resolve(x + y);}


async function calculate(){
   const value = await sum(5, 3);
   console.log("Rezultatul operațiunii asincrone:", value);
}
calculate();    // Rezultatul operațiunii asincrone: 8

Aici am definit funcția asincronă calculate(), la care se aplică async:

async function calculate(){

În interiorul funcției se apelează operațiunea asincronă sum(), căreia i se transmit niște valori. Și la această funcție se aplică operatorul await. Datorită operatorului await, nu mai este necesar să apelăm metoda then() la promise. Rezultatul returnat de Promise poate fi obținut direct din apelul funcției sum și, de exemplu, atribuit unei constante sau unei variabile:

const value = await sum(5, 3);

Apoi putem apela funcția calculate() ca o funcție obișnuită pentru a executa toate acțiunile sale.

calculate();

Trebuie să menționăm că pentru o funcție definită cu cuvântul async se creează implicit un obiect Promise. Prin urmare, o putem utiliza și ca un promise:

function sum(x, y){
   return new Promise(function(resolve){
       const result = x + y;
     

resolve(result);
   });
}

async function calculate(){
   const result = await sum(5, 3);
   return result;
}
calculate().then(value=> console.log("Rezultatul operațiunii asincrone:", value));

Executarea secvențială a operațiunilor asincrone

O funcție asincronă poate conține mai multe operațiuni asincrone la care se aplică operatorul await. În acest caz, toate operațiunile asincrone vor fi executate secvențial:

function sum(x, y){
   return new Promise(function(resolve){
       const result = x + y;
       resolve(result);
   });
}

async function calculate(){
   const value1 = await sum(5, 3);
   console.log("Rezultatul 1 al operațiunii asincrone:", value1);
   const value2 = await sum(6, 4);
   console.log("Rezultatul 2 al operațiunii asincrone:", value2);
   const value3 = await sum(7, 5);
   console.log("Rezultatul 3 al operațiunii asincrone:", value3);
}
calculate();    
// Rezultatul 1 al operațiunii asincrone: 8
// Rezultatul 2 al operațiunii asincrone: 10
// Rezultatul 3 al operațiunii asincrone: 12

Tratarea erorilor

Pentru tratarea erorilor care pot apărea în timpul apelului unei operațiuni asincrone se utilizează construcția try..catch..finally.

De exemplu, să luăm următorul cod care folosește Promise:

function square(str){
   return new Promise((resolve, reject) => {
       const n = parseInt(str);
       if (isNaN(n)) reject("Not a number");
       else resolve(n * n);
   });
};
function calculate(str){
   
   square(str)
       .then(value => console.log("Result: ", value))
       .catch(error => console.log(error));
}

calculate("g8");    // Not a number
calculate("4");     // Result:  16

Funcția square() primește o valoare oarecare, iar în promise această valoare este convertită în număr. Și în caz de succes, din promise se returnează pătratul numărului. Dacă valoarea transmisă nu este un număr, atunci se returnează o eroare.

La apelarea funcției square() cu metoda catch() putem trata eroarea apărută.

Acum să rescriem exemplul folosind async/await:

function square(str){
   return new Promise((resolve, reject) => {
       const n = parseInt(str);
       if (isNaN(n)) reject("Not a number");
       else resolve(n * n);
   })
};

async function calculate(str){
   
   try{
       const value = await square(str);
       console.log("Result: ", value);
   }
   catch(error){
       console.log(error);
   }
}

calculate("g8");    // Not a number
calculate("4");     // Result:  16

Apelul operațiunii asincrone este plasat în blocul try, iar în blocul catch putem obține eroarea apărută și o putem trata.

← Lecția anterioară Lecția următoare →