Ce este și cum se folosește

Când scrieți aplicații JavaScript, este posibil să fi întâlnit funcții asincrone, cum ar fi funcția de preluare din browser sau funcția readFile din Nodejs.

Este posibil să fi obținut rezultate neașteptate dacă ați folosit oricare dintre aceste funcții ca de obicei. Acest lucru se datorează faptului că sunt funcții asincrone. Acest articol vă îndrumă ce înseamnă asta și cum să utilizați funcțiile asincrone ca un profesionist.

Introducere în funcția sincronă

JavaScript este un limbaj cu un singur thread care poate face doar un singur lucru la un moment dat. Aceasta înseamnă că, dacă procesorul întâlnește o funcție care durează mult timp, JavaScript așteaptă până când întreaga funcție a fost executată înainte de a trece la alte părți ale programului.

Majoritatea funcțiilor sunt executate integral de procesor. Aceasta înseamnă că în timpul executării funcțiilor menționate, indiferent de cât timp durează, procesorul va fi complet ocupat. Acestea se numesc funcții sincrone. Un exemplu de funcție sincronă a fost definit mai jos:

function add(a, b) {
    for (let i = 0; i < 1000000; i ++) {
        // Do nothing
    }
    return a + b;
}

// Calling the function will take a long time
sum = add(10, 5);

// However, the processor cannot move to the 
console.log(sum);

Această funcție realizează o buclă mare a cărei execuție durează mult timp înainte de a returna suma celor două argumente ale sale.

După ce am definit funcția, am numit-o și am stocat rezultatul acesteia în variabila sumă. Apoi, am înregistrat valoarea variabilei sumă. Chiar dacă executarea funcției de adăugare durează un timp, procesorul nu poate trece la înregistrarea sumei până când execuția este completă.

Marea majoritate a funcțiilor pe care le veți întâlni se vor comporta în moduri previzibile, precum cea de mai sus. Cu toate acestea, unele funcții sunt asincrone și nu se comportă ca funcțiile obișnuite.

Introducere în funcția asincronă

Funcțiile asincrone își fac cea mai mare parte a muncii în afara procesorului. Aceasta înseamnă că, deși funcția poate dura ceva timp până la finalizarea execuției, procesorul va fi neocupat și va fi liber să lucreze mai mult.

Iată un exemplu de astfel de funcție:

fetch('https://jsonplaceholder.typicode.com/users/1');

Pentru a spori eficiența, JavaScript permite procesorului să treacă la alte sarcini care necesită CPU chiar înainte ca execuția funcției asincrone să fie finalizată.

Deoarece procesorul a continuat înainte ca execuția funcției asincrone să fie finalizată, rezultatul acesteia nu va fi disponibil imediat. Va fi în așteptare. Dacă procesorul ar încerca să execute alte părți ale programului care depind de rezultatul așteptat, am primi erori.

  Cunoașteți elementele de bază ale arhitecturii informaționale în proiectare [+4 Tools]

Prin urmare, procesorul ar trebui să execute doar părți ale programului care nu depind de rezultatul în așteptare. Pentru a face acest lucru, JavaScript modern utilizează promisiuni.

Ce este o promisiune în JavaScript?

În JavaScript, o promisiune este o valoare temporară pe care o returnează o funcție asincronă. Promisiunile sunt coloana vertebrală a programării asincrone moderne în JavaScript.

După ce o promisiune este creată, se întâmplă unul din două lucruri. Fie se rezolvă atunci când valoarea returnată a funcției asincrone este produsă cu succes, fie se respinge în cazul unei erori. Acestea sunt evenimente din ciclul de viață al unei promisiuni. Prin urmare, putem atașa handlere de evenimente la promisiunea care urmează să fie apelată atunci când rezolvă sau respinge.

Tot codul care necesită valoarea finală a unei funcții asincrone poate fi atașat la handlerul de evenimente al promisiunii pentru când se rezolvă. Tot codul care se ocupă de eroarea unei promisiuni respinse va fi, de asemenea, atașat la handlerul de evenimente corespunzător.

Iată un exemplu în care citim date dintr-un fișier în Nodejs.

const fs = require('fs/promises');

fileReadPromise = fs.readFile('./hello.txt', 'utf-8');

fileReadPromise.then((data) => console.log(data));

fileReadPromise.catch((error) => console.log(error));

În prima linie, importăm modulul fs/promises.

În a doua linie, apelăm funcția readFile, trecând numele și codificarea fișierului al cărui conținut dorim să-l citim. Această funcție este asincronă; prin urmare, returnează o promisiune. Stocăm promisiunea în variabila fileReadPromise.

În a treia linie, am atașat un ascultător de evenimente pentru când promisiunea se rezolvă. Am făcut acest lucru apelând metoda then pe obiectul promis. Ca argument pentru apelul nostru la metoda then, am transmis funcția pentru a rula dacă și când promisiunea se rezolvă.

În al patrulea rând, am atașat un ascultător pentru când promisiunea respinge. Acest lucru se face apelând metoda catch și trecând ca argument handler-ul de evenimente de eroare.

O abordare alternativă este folosirea cuvintelor cheie asincrone și așteptare. Vom acoperi această abordare în continuare.

Async și Await explicat

Cuvintele cheie Async și Await pot fi folosite pentru a scrie Javascript asincron într-un mod care arată mai bine din punct de vedere sintactic. În această secțiune, voi explica cum să utilizați cuvintele cheie și ce efect au acestea asupra codului dvs.

Cuvântul cheie await este folosit pentru a întrerupe execuția unei funcții în timp ce se așteaptă finalizarea unei funcții asincrone. Iată un exemplu:

const fs = require('fs/promises');

function readData() {
	const data = await fs.readFile('./hello.txt', 'utf-8');

    // This line will not be executed until the data becomes available
	console.log(data);
}

readData()

Am folosit cuvântul cheie await în timp ce facem un apel la readFile. Acest lucru a instruit procesorul să aștepte până când fișierul a fost citit înainte ca următoarea linie (consola.log) să poată fi executată. Acest lucru vă ajută să vă asigurați că codul care depinde de rezultatul unei funcții asincrone nu va fi executat până când rezultatul devine disponibil.

  Cum să devii un specialist Google Ads: 9 cursuri online

Dacă ați încerca să rulați codul de mai sus, veți întâlni o eroare. Acest lucru se datorează faptului că await poate fi utilizat numai în cadrul unei funcții asincrone. Pentru a declara o funcție ca asincronă, utilizați cuvântul cheie asincron înainte de declarația funcției astfel:

const fs = require('fs/promises');

async function readData() {
	const data = await fs.readFile('./hello.txt', 'utf-8');

    // This line will not be executed until the data becomes available
	console.log(data);
}

// Calling the function so it runs
readData()

// Code at this point will run while waiting for the readData function to complete
console.log('Waiting for the data to complete')

Rulând acest fragment de cod, veți vedea că JavaScript execută console.log exterior în timp ce așteptați ca datele citite din fișierul text să devină disponibile. Odată ce este disponibil, console.log din interiorul readData este executat.

Gestionarea erorilor în timpul utilizării cuvintelor cheie asincrone și așteptare se realizează de obicei folosind încearcă să prinzi blocuri. De asemenea, este important să știi cum buclă cu cod asincron.

Async și await sunt disponibile în JavaScript modern. În mod tradițional, codul asincron a fost scris prin utilizarea apelurilor inverse.

Introducere în apeluri inverse

Un apel invers este o funcție care va fi apelată odată ce rezultatul este disponibil. Tot codul care necesită valoarea returnată va fi introdus în callback. Orice altceva în afara callback-ului nu depinde de rezultat și, prin urmare, este liber să fie executat.

Iată un exemplu care citește un fișier în Nodejs.

const fs = require("fs");

fs.readFile("./hello.txt", "utf-8", (err, data) => {

	// In this callback, we put all code that requires 
	if (err) console.log(err);
	else console.log(data);
});

// In this part here we can perform all the tasks that do not require the result
console.log("Hello from the program")

În prima linie, am importat modulul fs. Apoi, am numit funcția readFile a modulului fs. Funcția readFile va citi text dintr-un fișier pe care îl specificăm. Primul argument este ce fișier este, iar al doilea specifică formatul fișierului.

Funcția readFile citește textul din fișiere în mod asincron. Pentru a face acest lucru, ia o funcție ca argument. Acest argument al funcției este o funcție de apel invers și va fi apelat odată ce datele au fost citite.

Primul argument transmis atunci când funcția de apel invers este apelată este o eroare care va avea o valoare dacă apare o eroare în timp ce funcția rulează. Dacă nu se întâlnește nicio eroare, aceasta va fi nedefinită.

Al doilea argument transmis callback-ului sunt datele citite din fișier. Codul din această funcție va accesa datele din fișier. Codul din afara acestei funcții nu necesită date din fișier; prin urmare, poate fi executat în așteptarea datelor din fișier.

  5 alternative gratuite la Midjourney

Rularea codului de mai sus ar produce următorul rezultat:

Caracteristici cheie JavaScript

Există câteva caracteristici și caracteristici cheie care influențează modul în care funcționează JavaScript asincron. Sunt bine explicate în videoclipul de mai jos:

Am subliniat pe scurt cele două caracteristici importante mai jos.

#1. Cu un singur fir

Spre deosebire de alte limbi care permit programatorului să folosească mai multe fire, JavaScript vă permite să utilizați doar un fir. Un fir este o secvență de instrucțiuni care depind logic una de alta. Firele multiple permit programului să execute un fir diferit atunci când sunt întâlnite operațiuni de blocare.

Cu toate acestea, firele multiple adaugă complexitate și îngreunează înțelegerea programelor care le folosesc. Acest lucru face mai probabil ca erori să fie introduse în cod și ar fi dificil să depanați codul. JavaScript a fost creat cu un singur thread pentru simplitate. Fiind un limbaj cu un singur thread, se bazează pe faptul că este bazat pe evenimente pentru a gestiona eficient operațiunile de blocare.

#2. Condus de evenimente

JavaScript este, de asemenea, bazat pe evenimente. Aceasta înseamnă că unele evenimente au loc în timpul ciclului de viață al unui program JavaScript. În calitate de programator, puteți atașa funcții acestor evenimente și, ori de câte ori are loc evenimentul, funcția atașată va fi apelată și executată.

Unele evenimente ar putea rezulta din faptul că rezultatul unei operațiuni de blocare este disponibil. În acest caz, funcția asociată este apoi apelată cu rezultatul.

Lucruri de luat în considerare atunci când scrieți JavaScript asincron

În această ultimă secțiune, voi menționa câteva lucruri de luat în considerare atunci când scrieți JavaScript asincron. Aceasta va include suport pentru browser, cele mai bune practici și importanță.

Suport pentru browser

Acesta este un tabel care arată suportul promisiunilor în diferite browsere.

Sursă: caniuse.com

Acesta este un tabel care arată compatibilitatea cuvintelor cheie asincrone în diferite browsere.

Sursă: caniuse.com

Cele mai bune practici

  • Optați întotdeauna pentru async/wait, deoarece vă ajută să scrieți cod mai curat la care este ușor de gândit.
  • Gestionați erorile din blocurile try/catch.
  • Utilizați cuvântul cheie async numai atunci când este necesar să așteptați rezultatul unei funcții.

Importanța codului asincron

Codul asincron vă permite să scrieți programe mai eficiente care folosesc doar un fir. Acest lucru este important deoarece JavaScript este utilizat pentru a construi site-uri web care efectuează o mulțime de operațiuni asincrone, cum ar fi solicitări de rețea și citirea sau scrierea fișierelor pe disc. Această eficiență a permis timpilor de execuție precum NodeJS să crească în popularitate ca timp de rulare preferat pentru serverele de aplicații.

Cuvinte finale

Acesta a fost un articol lung, dar în el am putut acoperi modul în care funcțiile asincrone diferă de funcțiile sincrone obișnuite. Am abordat, de asemenea, cum să folosiți codul asincron folosind doar promisiuni, cuvinte cheie asincrone/așteptare și apeluri inverse.

În plus, am acoperit caracteristicile cheie ale JavaScript. În ultima secțiune, am încheiat acoperind suportul pentru browser și cele mai bune practici.

Apoi, consultați întrebările frecvente ale interviului Node.js.