'n Beginnersgids vir asynchrone JavaScript

javascript
beloftes
AsyncWag
'n Beginnersgids vir asynchrone JavaScript cover image

As jy eers met programmering begin, is die kans groot dat jy aan programme dink as 'n stel opeenvolgende blokke van logika, waar elke blok 'n spesifieke ding doen en sy resultaat deurgee sodat die volgende blok kan loop en so aan, en vir die Meeste deel jy is reg, die meeste programme loop op 'n opeenvolgende manier, hierdie model stel ons in staat om programme te bou wat maklik is om te skryf en in stand te hou. Daar is egter spesifieke gebruiksgevalle waar hierdie opeenvolgende model nie sou werk nie, of nie optimaal sou wees nie. Oorweeg as voorbeeld 'n boeklesertoepassing. Hierdie toepassing het 'n paar gevorderde kenmerke soos om alle voorkoms van 'n woord te vind, navigeer tussen boekmerke en dergelike. Stel jou nou voor dat die gebruiker tans 'n lang boek lees en besluit om na al die voorkoms van 'n algemene woord soos "Die" te soek. Die toepassing sal gewoonlik 'n paar sekondes neem om al die voorkoms van daardie woord te vind en te indekseer. In 'n opeenvolgende program kan die gebruiker nie met die toepassing interaksie hê nie (die bladsy verander of 'n teks uitlig) totdat die soekbewerking voltooi is. Hopelik kan u sien dat dit nie 'n optimale gebruikerservaring is nie!

1

Die diagram illustreer 'n tipiese uitvoeringsvloei van die boeklesertoepassing. As die gebruiker 'n langlopende operasie begin (in hierdie geval die soektog na alle voorkomste van "die" in 'n groot boek), "vries" die toepassing vir die hele duur van daardie operasie. In hierdie geval sal die gebruiker aanhou om op die volgende boekmerkknoppie te klik sonder enige resultaat totdat die soekbewerking voltooi is en al die bewerkings sal gelyktydig in werking tree, wat die eindgebruiker die gevoel gee van 'n sloerende toepassing.

Jy het dalk opgemerk dat hierdie voorbeeld nie regtig ooreenstem met die opeenvolgende model wat ons vroeër bekendgestel het nie. Dit is omdat die bedrywighede hier onafhanklik van mekaar is. Die gebruiker hoef nie te weet van die aantal gevalle van "die" om na die volgende boekmerk te navigeer nie, so die volgorde van uitvoering van bewerkings is nie regtig belangrik nie. Ons hoef nie te wag vir die einde van die soektog voordat ons na die volgende boekmerk kan navigeer nie. 'n Moontlike verbetering van die vorige uitvoeringsvloei is gebaseer op hierdie logika: ons kan die lang soekoperasie op die agtergrond uitvoer, voortgaan met enige inkomende bewerkings, en sodra die lang bewerking gedoen is, kan ons die gebruiker eenvoudig in kennis stel. Die uitvoeringsvloei word soos volg:

2

Met hierdie uitvoeringsvloei word die gebruikerservaring aansienlik verbeter. Nou kan die gebruiker 'n langlopende bewerking begin, voortgaan om die toepassing normaal te gebruik en in kennis gestel word sodra die bewerking voltooi is. Dit is die basis van asinchroniese programmering.

Javascript, onder andere, ondersteun hierdie styl van asinchroniese programmering deur uitgebreide API's te verskaf om omtrent enige asynchrone gedrag waaraan jy kan dink, te bereik. Aan die einde van die dag moet Javascript inherent 'n asinchrone taal wees. As ons na die vorige voorbeeld verwys, is die asynchrone logika aan die basis van alle gebruikersinteraksie-toepassings, en Javascript is hoofsaaklik gebou om op die blaaier gebruik te word waar die meeste van die programme daarop gaan om op gebruikersaksies te reageer.

Die volgende sal jou 'n kort gids gee oor Asynchronous Javascript:

Terugbelle

In 'n tipiese program sal jy gewoonlik 'n aantal funksies vind. Om 'n funksie te gebruik, noem ons dit met 'n stel parameters. Die funksie kode sal uitvoer en 'n resultaat gee, niks buitengewoon nie. Asinchroniese programmering verskuif hierdie logika effens. Om terug te gaan na die voorbeeld van die boekleser-toepassing, ons kan nie 'n gewone funksie gebruik om die soekbewerkingslogika te implementeer nie, aangesien die bewerking 'n onbekende hoeveelheid tyd neem. 'n Gereelde funksie sal basies terugkeer voordat die operasie gedoen word, en dit is nie die gedrag wat ons verwag nie. Die oplossing is om 'n ander funksie te spesifiseer wat uitgevoer sal word sodra die soekbewerking gedoen is. Dit modelleer ons gebruiksgeval aangesien ons program normaalweg kan voortgaan en sodra die soekbewerking voltooi is, sal die gespesifiseerde funksie uitgevoer word om die gebruiker van die soekresultate in kennis te stel. Hierdie funksie is wat ons 'n terugbelfunksie noem:

// Search occurrences function
function searchOccurrences(word, callback) {
  try {
    // search operation logic, result is in result variable
    //....
    callback(null, word, result);
  } catch (err) {
    callback(err);
  }
}

// Search occurrences callback function
function handleSearchOccurrencesResult(err, word, result) {
  if (err) {
    console.log(`Search operation for ${word} ended with an error`);
  } else console.log(`Search results for ${word}: ${result}`);
  return;
}

searchOccurrences("the", handleSearchOccurrencesResult);

Eerstens definieer ons die soekbewerkingsfunksie, searchOccurrences. Dit neem die woord om na te soek en 'n tweede parameter "terugbel" wat die funksie sal wees om uit te voer sodra die soekbewerking gedoen is. Die soekbewerkingsfunksie is doelbewus abstrak gehou, ons hoef net op sy twee moontlike uitkomste te fokus: die eerste geval is waar alles suksesvol was en ons het die resultaat van die soektog in die resultaatveranderlike. In hierdie geval moet ons net die terugbelfunksie oproep met die volgende parameters: die eerste parameter is nul wat beteken dat geen fout voorgekom het nie, die tweede parameter is die woord wat gesoek is, en die derde en miskien belangrikste parameter van die drie, is die resultaat van die soekoperasie.

Die tweede geval is waar 'n fout voorkom, dit is ook 'n geval waar die uitvoering van die soekoperasie gedoen word en ons die terugbelfunksie moet oproep. Ons gebruik 'n probeer-en-vang-blok om enige fout te onderskep en ons roep net die terugbelfunksie met die foutvoorwerp van die vangblok af.

Ons het toe die terugbelfunksie gedefinieer, handleSearchOccurrences, ons het die logika daarvan redelik eenvoudig gehou. Dit is net 'n kwessie om 'n boodskap na die konsole te druk. Ons gaan eers die "err" parameter na om te sien of enige fout in die hooffunksie voorgekom het. In daardie geval laat ons net die gebruiker weet dat die soekoperasie met 'n fout geëindig het. As daar geen foute gemaak is nie, druk ons ​​'n boodskap met die resultaat van die soektog.

Laastens noem ons die searchOccurrences-funksie met die woord "die". Die funksie sal nou normaal loop sonder om die hoofprogram te blokkeer en sodra die soektog gedoen is, sal die terugbel uitgevoer word en ons sal die resultaatboodskap óf met die soekresultaat óf die foutboodskap kry.

Dit is belangrik om hier te noem dat ons slegs toegang het tot die resultaatveranderlike binne die hoof- en die terugbelfunksies. As ons so iets probeer:

let result;
function searchOccurrences(word, callback) {
  try {
    // search operation logic, result is in searchResult variable
    //....
    result = searchResult;
    callback(null, word, result);
  } catch (err) {
    callback(err);
  }
}
searchOccurrences("the", handleSearchOccurrencesResult);
console.log(result);

die resultaat van die druk sou ongedefinieerd wees omdat die programme nie wag vir die searchOccurrences-funksie om uit te voer nie. Dit beweeg na die volgende instruksie wat die drukstelling is voordat die resultaatveranderlike binne die hooffunksie toegewys word. As gevolg hiervan, sal ons die ontoegekende resultaat veranderlike druk.

Dus, gebaseer op hierdie logika, moet ons al die kode wat die resultaatveranderlike gebruik binne die terugbelfunksie hou. Dit lyk dalk nie nou 'n probleem nie, maar dit kan vinnig eskaleer in 'n werklike probleem. Stel jou die geval voor waar ons 'n ketting van asynchrone funksies het wat in volgorde moet loop. In die tipiese terugbellogika sal jy iets soos hierdie implementeer:

functionA(function (err, resA) {
  ///......
  functionB(resA, function (err, resB) {
    ///......
    functionC(resB, function (err, resC) {
      ///......
      functionD(resC, function (err, resD) {
        ///......
      });
    });
  });
});

Hou in gedagte dat elke terugbel 'n foutparameter het en elke fout moet afsonderlik hanteer word. Dit maak die reeds komplekse kode hierbo selfs meer kompleks en moeilik om te onderhou. Hopelik is Promises hier om die terugbelprobleem op te los, ons sal dit volgende dek.

Beloftes

Beloftes word bo-op terugbelopings gebou en werk op 'n soortgelyke wyse. Hulle is bekendgestel as deel van ES6-kenmerke om 'n paar van die opvallende probleme met terugbelopings op te los, soos terugbelhel. Beloftes verskaf hul eie funksies wat loop op suksesvolle voltooiing (op te los), en wanneer foute voorkom (verwerp). Die volgende wys die searchOccurrences-voorbeeld wat met beloftes geïmplementeer is:

// Search occurrences function
function searchOccurrences(word) {
  return new Promise((resolve, reject) => {
    try {
      // search operation logic, result is in result variable
      //....
      resolve(word, result);
    } catch (err) {
      reject(err);
    }
  });
}

searchOccurrences("the")
  .then((word, result) => {
    console.log(`Search results for ${word}: ${result}`);
  })
  .catch((err) => {
    console.log(`Search operation ended with an error`);
  });

Kom ons gaan oor die veranderinge wat ons toegepas het:

Die searchOccurrences-funksie gee 'n belofte terug. Binne die belofte behou ons dieselfde logika: ons het twee funksies om op te los en te verwerp wat ons terugbelopings verteenwoordig eerder as om 'n enkele terugbelfunksie te hê wat beide 'n suksesvolle uitvoering en 'n uitvoering met foute hanteer. Beloftes skei die twee uitkomste en verskaf 'n skoon sintaksis wanneer die hooffunksie geroep word. Die oplossingsfunksie is "gehaak" aan die hooffunksie deur die "dan" sleutelwoord te gebruik. Hier spesifiseer ons net die twee parameters van die oplossingsfunksie en druk die soekresultaat. 'N Soortgelyke ding is van toepassing op die verwerp-funksie, dit kan gekoppel word met die "vang"-sleutelwoord. Hopelik kan u die voordele waardeer wat beloftes bied in terme van kodeleesbaarheid en netheid. As jy nog daaroor debatteer, kyk hoe ons die terugbelprobleem kan oplos deur die asynchrone funksies saam te ketting om die een na die ander uit te voer:

searchOccurrences("the")
  .then(searchOccurrences("asynchronous"))
  .then(searchOccurrences("javascript"))
  .then(searchOccurrences("guide"))
  .catch((err) => {
    console.log(`Search operation ended with an error`);
  });

Async/Wag

Async/Wag is die nuutste toevoeging tot ons asynchrone gereedskapgordel in Javascript. Ingestel met ES8, bied hulle 'n nuwe laag van abstraksie bo-op asinchroniese funksies deur eenvoudig te "wag" vir die uitvoering van 'n asinchrone bewerking. Die vloei van die program blokkeer by daardie instruksie totdat 'n resultaat van die asinchrone bewerking teruggestuur word en dan sal die program voortgaan met die volgende instruksie. As jy aan die sinchroniese uitvoeringsvloei dink, is jy korrek. Ons het 'n volle sirkel gekom! Async/wait pogings om die eenvoud van sinchroniese programmering na die asinchrone wêreld te bring. Hou asseblief in gedagte dat dit slegs in die uitvoering en die kode van die program waargeneem word. Alles bly dieselfde onder die enjinkap, Async/await gebruik steeds beloftes en terugbelle is hul boustene.

Kom ons gaan oor ons voorbeeld en implementeer dit met Async/await:

async function searchOccurrences(word) {
  try {
    // search operation logic, result is in result variable
    //....
    return result;
  } catch (err) {
    console.log(`Search operation for ${word} ended with an error`);
  }
}

const word = "the";

const result = await searchOccurrences(word, handleSearchOccurrencesResult);

console.log(`Search results for ${word}: ${result}`);

Ons kode het nie veel verander nie, die belangrikste ding om hier op te let is die "async" sleutelwoord voor die searchOccurrences-funksieverklaring. Dit dui aan dat die funksie asynchronies is. Let ook op die "wag" sleutelwoord wanneer jy die searchOccurrences-funksie oproep. Dit sal die program opdrag gee om te wag vir die uitvoering van die funksie totdat die resultaat teruggestuur word voordat die program na die volgende instruksie kan beweeg, met ander woorde, die resultaatveranderlike sal altyd die teruggekeerde waarde van die searchOccurrences-funksie hou en nie die belofte van die funksie, in daardie sin, Async/Wag het nie 'n hangende toestand as Beloftes nie. Sodra die uitvoering gedoen is, beweeg ons na die drukstaat en hierdie keer bevat die resultaat eintlik die resultaat van die soekoperasie. Soos verwag, het die nuwe kode dieselfde gedrag asof dit sinchronies is.

Nog 'n klein ding om in gedagte te hou, is dat aangesien ons nie meer terugbelfunksies het nie, ons die searchOccurrences-fout in dieselfde funksie moet hanteer, aangesien ons nie net die fout na die terugbelfunksie kan versprei en dit daar hanteer nie. Hier druk ons ​​net 'n foutboodskap in die geval van 'n fout ter wille van die voorbeeld.

Afsluiting

In hierdie artikel het ons deur die verskillende benaderings gegaan wat gebruik word om asinchrone logika in Javascript te implementeer. Ons het begin deur 'n konkrete voorbeeld te ondersoek van hoekom ons van die gewone sinchrone styl van programmering na die asinchrone model sou moes oorskakel. Ons het toe na terugbelopings beweeg, wat die hoofboublokke van asynchrone Javascript is. Die beperkings van terugbelopings het ons gelei na die verskillende alternatiewe wat oor die jare bygevoeg is om hierdie beperkings te oorkom, hoofsaaklik beloftes en Async/wag. Asinchrone logika kan oral op die web gevind word, of jy nou 'n eksterne API roep, 'n databasisnavraag begin, na die plaaslike lêerstelsel skryf, of selfs wag vir gebruikersinvoer op 'n aanmeldvorm. Hopelik voel jy nou meer selfversekerd om hierdie kwessies aan te pak deur skoon en onderhoubare Asynchronous Javascript te skryf!

As jy van hierdie artikel hou, kyk asseblief na die CLA Blog waar ons verskeie onderwerpe bespreek oor hoe om in tegnologie te kom. Kyk ook na ons youtube-kanaal vir ons vorige gratis werkswinkels en volg ons op sosiale media sodat jy nie opkomendes misloop nie!


Toekomsbestendig jou loopbaan deur vaardighede in HTML, CSS en JavaScript op te gradeer met Code Labs Academy se Web Development Bootcamp.


Career Services background pattern

Loopbaandienste

Contact Section background image

Kom ons bly in kontak

Code Labs Academy © 2024 Alle regte voorbehou.