logo

Atzvanīšanas elle JavaScript

JavaScript ir asinhrona (nebloķējoša) un viena pavediena programmēšanas valoda, kas nozīmē, ka vienlaikus var palaist tikai vienu procesu.

Programmēšanas valodās atzvanīšanas elle parasti attiecas uz neefektīvu veidu, kā ierakstīt kodu ar asinhroniem zvaniem. To sauc arī par Nolemtības piramīdu.

JavaScript atzvanīšanas elle tiek saukta par situāciju, kad tiek izpildīts pārāk daudz ligzdotu atzvanīšanas funkciju. Tas samazina koda lasāmību un apkopi. Atzvanīšanas elles situācija parasti rodas, veicot asinhrono pieprasījumu operācijas, piemēram, veicot vairākus API pieprasījumus vai apstrādājot notikumus ar sarežģītām atkarībām.

Lai labāk izprastu JavaScript atzvanīšanas elli, vispirms izprotiet atzvanīšanas un notikumu cilpas JavaScript.

Atzvani JavaScript

JavaScript visu uzskata par objektu, piemēram, virknes, masīvus un funkcijas. Tādējādi atzvanīšanas koncepcija ļauj mums nodot funkciju kā argumentu citai funkcijai. Atzvanīšanas funkcija vispirms pabeigs izpildi, un vecākfunkcija tiks izpildīta vēlāk.

Atzvanīšanas funkcijas tiek izpildītas asinhroni un ļauj kodam turpināt darboties, negaidot asinhronā uzdevuma pabeigšanu. Ja tiek apvienoti vairāki asinhroni uzdevumi un katrs uzdevums ir atkarīgs no tā iepriekšējā uzdevuma, koda struktūra kļūst sarežģīta.

Izpratīsim atzvanīšanas lietojumu un nozīmi. Pieņemsim, ka mums ir funkcija, kas ņem trīs parametrus, vienu virkni un divus skaitļus. Mēs vēlamies izvadi, pamatojoties uz virknes tekstu ar vairākiem nosacījumiem.

Apsveriet tālāk sniegto piemēru:

 function expectedResult(action, x, y){ if(action === 'add'){ return x+y }else if(action === 'subtract'){ return x-y } } console.log(expectedResult('add',20,10)) console.log(expectedResult('subtract',30,10)) 

Izvade:

 30 20 

Iepriekš minētais kods darbosies labi, taču mums ir jāpievieno vairāk uzdevumu, lai kods būtu mērogojams. Nosacīto priekšrakstu skaits arī turpinās palielināties, kas novedīs pie netīras koda struktūras, kas ir jāoptimizē un lasāma.

Tātad, mēs varam pārrakstīt kodu labākā veidā šādi:

 function add(x,y){ return x+y } function subtract(x,y){ return x-y } function expectedResult(callBack, x, y){ return callBack(x,y) } console.log(expectedResult(add, 20, 10)) console.log(expectedResult(subtract, 30, 10)) 

Izvade:

 30 20 

Tomēr rezultāts būs tāds pats. Taču iepriekš minētajā piemērā mēs esam definējuši tās atsevišķo funkcijas pamattekstu un nodevuši funkciju kā atzvanīšanas funkciju gaidītāResult funkcijai. Tādējādi, ja mēs vēlamies paplašināt gaidāmo rezultātu funkcionalitāti, lai mēs varētu izveidot citu funkcionējošu pamattekstu ar citu darbību un izmantot to kā atzvanīšanas funkciju, tas atvieglos koda lasāmības izpratni un uzlabos to.

Ir arī citi dažādi atzvanīšanas piemēri, kas ir pieejami atbalstītajās JavaScript funkcijās. Daži izplatīti piemēri ir notikumu uztvērēji un masīva funkcijas, piemēram, kartēšana, samazināšana, filtrēšana utt.

Lai to labāk izprastu, mums ir jāsaprot JavaScript garāmejošā vērtība un atsauce.

JavaScript atbalsta divu veidu datu tipus, kas ir primitīvi un neprimitīvi. Primitīvie datu tipi ir nedefinēti, nulles, virkne un Būla, kurus nevar mainīt, vai mēs varam teikt salīdzinoši nemainīgi; neprimitīvie datu tipi ir masīvi, funkcijas un objekti, kurus var mainīt vai mainīt.

Pass by reference nodod entītijas atsauces adresi, tāpat kā funkciju var uzskatīt par argumentu. Tātad, ja šīs funkcijas vērtība tiek mainīta, tā mainīs sākotnējo vērtību, kas ir pieejama ārpus funkcijas.

Salīdzinoši, garāmbraukšanas vērtības koncepcija nemaina tās sākotnējo vērtību, kas ir pieejama ārpus funkcijas pamatteksta. Tā vietā vērtība tiks kopēta divās dažādās vietās, izmantojot to atmiņu. JavaScript identificēja visus objektus pēc to atsauces.

JavaScript programmā addEventListener klausās notikumus, piemēram, klikšķi, peles kursora novietošanu un peles kursora izņemšanu, un izmanto otro argumentu kā funkciju, kas tiks izpildīta, tiklīdz notikums tiks aktivizēts. Šī funkcija tiek izmantota pēc atsauces jēdziena un tiek nodota bez iekavām.

Apsveriet tālāk sniegto piemēru; šajā piemērā mēs esam nodevuši sveiciena funkciju kā argumentu addEventListener kā atzvanīšanas funkcijai. Tas tiks izsaukts, kad tiks aktivizēts klikšķa notikums:

Test.html:

 Javascript Callback Example <h3>Javascript Callback</h3> Click Here to Console const button = document.getElementById(&apos;btn&apos;); const greet=()=&gt;{ console.log(&apos;Hello, How are you?&apos;) } button.addEventListener(&apos;click&apos;, greet) 

Izvade:

Atzvanīšanas elle JavaScript

Iepriekš minētajā piemērā mēs esam nodevuši sveiciena funkciju kā argumentu addEventListener kā atzvanīšanas funkcijai. Tas tiks izsaukts, kad tiks aktivizēts klikšķa notikums.

Tāpat filtrs ir arī atzvanīšanas funkcijas piemērs. Ja masīva atkārtošanai izmantojam filtru, masīva datu apstrādei kā arguments tiks izmantota cita atzvanīšanas funkcija. Apsveriet tālāk sniegto piemēru; šajā piemērā mēs izmantojam lielāko funkciju, lai masīvā izdrukātu skaitli, kas ir lielāks par 5. Mēs izmantojam funkciju isGreater kā atzvanīšanas funkciju filtra metodē.

konvertēt virkni uz datumu
 const arr = [3,10,6,7] const isGreater = num =&gt; num &gt; 5 console.log(arr.filter(isGreater)) 

Izvade:

 [ 10, 6, 7 ] 

Iepriekš minētais piemērs parāda, ka lielākā funkcija filtra metodē tiek izmantota kā atzvanīšanas funkcija.

Lai labāk izprastu atzvanīšanas, notikumu cilpas JavaScript, apspriedīsim sinhrono un asinhrono JavaScript:

Sinhronais JavaScript

Sapratīsim, kādas ir sinhronās programmēšanas valodas iezīmes. Sinhronajai programmēšanai ir šādas funkcijas:

Izpildes bloķēšana: Sinhronā programmēšanas valoda atbalsta bloķēšanas izpildes paņēmienu, kas nozīmē, ka tā bloķē nākamo paziņojumu izpildi, esošie paziņojumi tiks izpildīti. Tādējādi tiek panākta paredzama un deterministiska paziņojumu izpilde.

Secīgā plūsma: Sinhronā programmēšana atbalsta secīgu izpildes plūsmu, kas nozīmē, ka katrs paziņojums tiek izpildīts secīgi tāpat kā viens pēc otra. Valodas programma gaida, līdz paziņojums tiks pabeigts, pirms pāriet uz nākamo.

Vienkāršība: Bieži vien sinhronā programmēšana tiek uzskatīta par viegli saprotamu, jo mēs varam paredzēt tās izpildes plūsmas secību. Parasti tas ir lineārs un viegli paredzams. Mazās lietojumprogrammas ir labi izstrādātas šajās valodās, jo tās var apstrādāt kritisko darbību secību.

Tieša kļūdu apstrāde: Sinhronā programmēšanas valodā kļūdu apstrāde ir ļoti vienkārša. Ja paziņojuma izpildes laikā rodas kļūda, tā parādīs kļūdu, un programma to var uztvert.

Īsumā, sinhronajai programmēšanai ir divas galvenās funkcijas, t.i., vienlaikus tiek izpildīts viens uzdevums, un nākamā uzdevumu kopa tiks risināta tikai tad, kad pašreizējais uzdevums būs pabeigts. Tādējādi tas seko secīgai koda izpildei.

Šī programmēšanas darbība, izpildot paziņojumu, valoda rada bloka koda situāciju, jo katram darbam ir jāgaida, līdz tiek pabeigts iepriekšējais darbs.

Bet, kad cilvēki runā par JavaScript, tā vienmēr ir bijusi mulsinoša atbilde, vai tas ir sinhrons vai asinhrons.

Iepriekš apspriestajos piemēros, kad filtra funkcijā izmantojām funkciju kā atzvanīšanu, tā tika izpildīta sinhroni. Tāpēc to sauc par sinhrono izpildi. Filtra funkcijai jāgaida, līdz lielākā funkcija pabeigs tās izpildi.

Tādējādi atzvanīšanas funkciju sauc arī par atzvanīšanas bloķēšanu, jo tā bloķē vecākfunkcijas izpildi, kurā tā tika izsaukta.

Pirmkārt, JavaScript tiek uzskatīts par viena pavediena sinhronu un bloķējošu raksturu. Taču, izmantojot dažas pieejas, mēs varam panākt, lai tas darbotos asinhroni, pamatojoties uz dažādiem scenārijiem.

Tagad sapratīsim asinhrono JavaScript.

Asinhronais JavaScript

Asinhronā programmēšanas valoda koncentrējas uz lietojumprogrammas veiktspējas uzlabošanu. Šādos gadījumos var izmantot atzvanīšanu. Mēs varam analizēt JavaScript asinhrono uzvedību, izmantojot šādu piemēru:

 function greet(){ console.log(&apos;greet after 1 second&apos;) } setTimeout(greet, 1000) 

Iepriekš minētajā piemērā funkcija setTimeout kā argumentus izmanto atzvanīšanu un laiku milisekundēs. Atzvans tiek izsaukts pēc minētā laika (šeit 1s). Īsumā, funkcija gaidīs 1 s, līdz tā tiks izpildīta. Tagad apskatiet tālāk norādīto kodu:

 function greet(){ console.log(&apos;greet after 1 second&apos;) } setTimeout(greet, 1000) console.log(&apos;first&apos;) console.log(&apos;Second&apos;) 

Izvade:

 first Second greet after 1 second 

No iepriekš minētā koda žurnāla ziņojumi pēc setTimeout tiks izpildīti vispirms, kamēr taimeris paies garām. Tādējādi tiek parādīta viena sekunde un pēc 1 sekundes laika intervāla tiek parādīts sveiciena ziņojums.

Programmā JavaScript setTimeout ir asinhrona funkcija. Ikreiz, kad izsaucam funkciju setTimeout, tā reģistrē atzvanīšanas funkciju (šajā gadījumā sveicienu), kas jāizpilda pēc norādītās aizkaves. Tomēr tas nebloķē nākamā koda izpildi.

Iepriekš minētajā piemērā žurnāla ziņojumi ir sinhronie paziņojumi, kas tiek izpildīti nekavējoties. Tie nav atkarīgi no setTimeout funkcijas. Tāpēc viņi izpilda un reģistrē savus attiecīgos ziņojumus konsolē, negaidot setTimeout norādīto aizkavi.

Tikmēr JavaScript notikumu cilpa apstrādā asinhronos uzdevumus. Šajā gadījumā tas gaida, līdz paiet norādītā aizkave (1 sekunde), un pēc tam, kad šis laiks ir pagājis, tas uztver atzvanīšanas funkciju (sveiciens) un izpilda to.

Tādējādi otrs kods pēc funkcijas setTimeout tika izpildīts, darbojoties fonā. Šī darbība ļauj JavaScript veikt citus uzdevumus, gaidot asinhronās darbības pabeigšanu.

Mums ir jāsaprot zvanu steks un atzvanīšanas rinda, lai apstrādātu asinhronos notikumus JavaScript.

Apsveriet tālāk redzamo attēlu:

Atzvanīšanas elle JavaScript

No iepriekš redzamā attēla tipisks JavaScript dzinējs sastāv no kaudzes atmiņas un zvanu steka. Zvanu kaudze izpilda visu kodu, negaidot, kad tiek nospiests uz steku.

Kaudzes atmiņa ir atbildīga par atmiņas piešķiršanu objektiem un funkcijām izpildlaikā, kad vien tie ir nepieciešami.

Tagad mūsu pārlūkprogrammas dzinēji sastāv no vairākām tīmekļa API, piemēram, DOM, setTimeout, konsole, ielāde utt., un programma var piekļūt šīm API, izmantojot globālā loga objektu. Nākamajā darbībā dažas notikumu cilpas pilda vārtejas lomu, kas atlasa funkciju pieprasījumus atzvanīšanas rindā un ievieto tos kaudzē. Šīm funkcijām, piemēram, setTimeout, ir nepieciešams noteikts gaidīšanas laiks.

Tagad atgriezīsimies pie mūsu piemēra, funkcijas setTimeout; Kad funkcija tiek atklāta, taimeris tiek reģistrēts atzvanīšanas rindā. Pēc tam pārējais kods tiek iespiests izsaukuma kaudzē un tiek izpildīts, tiklīdz funkcija sasniedz taimera ierobežojumu, ir beidzies, un atzvanīšanas rinda nospiež atzvanīšanas funkciju, kurai ir norādītā loģika un kas ir reģistrēta taimauta funkcijā. . Tādējādi tas tiks izpildīts pēc noteiktā laika.

Atzvanīšanas elles scenāriji

Tagad mēs esam apsprieduši atzvanīšanas, sinhronās, asinhronās un citas atbilstošas ​​tēmas par atzvanīšanas elli. Sapratīsim, kas JavaScript ir atzvanīšanas elle.

Situācija, kad ir ligzdotas vairākas atzvanīšanas, ir pazīstama kā atzvanīšanas elli, jo tās koda forma izskatās kā piramīda, ko sauc arī par 'nolemtības piramīdu'.

Atzvanīšanas ellē ir grūtāk saprast un uzturēt kodu. Lielākoties šo situāciju varam redzēt, strādājot mezglā JS. Piemēram, apsveriet tālāk sniegto piemēru:

 getArticlesData(20, (articles) =&gt; { console.log(&apos;article lists&apos;, articles); getUserData(article.username, (name) =&gt; { console.log(name); getAddress(name, (item) =&gt; { console.log(item); //This goes on and on... } }) 

Iepriekš minētajā piemērā getUserData izmanto lietotājvārdu, kas ir atkarīgs no rakstu saraksta vai ir jāizvelk getArticles atbilde, kas atrodas rakstā. getAddress ir arī līdzīga atkarība, kas ir atkarīga no getUserData atbildes. Šo situāciju sauc par atzvanīšanas elli.

Atzvanīšanas elles iekšējo darbību var saprast, izmantojot šādu piemēru:

Sapratīsim, ka mums ir jāveic uzdevums A. Lai veiktu uzdevumu, mums ir nepieciešami daži dati no uzdevuma B. Līdzīgi; mums ir dažādi uzdevumi, kas ir atkarīgi viens no otra un tiek izpildīti asinhroni. Tādējādi tiek izveidota virkne atzvanīšanas funkciju.

Izpratīsim JavaScript solījumus un to, kā tie rada asinhronas darbības, ļaujot mums izvairīties no ligzdotu atzvanu rakstīšanas.

JavaScript sola

JavaScript solījumi tika ieviesti ES6. Tas ir objekts ar sintaktisku pārklājumu. Asinhronās darbības dēļ tas ir alternatīvs veids, kā izvairīties no asinhrono darbību atzvanīšanas rakstīšanas. Mūsdienās tīmekļa API, piemēram, fetch(), tiek ieviesti, izmantojot daudzsološo, kas nodrošina efektīvu veidu, kā piekļūt datiem no servera. Tas arī uzlaboja koda lasāmību un ir veids, kā izvairīties no ligzdotu atzvanu rakstīšanas.

Solījumi reālajā dzīvē pauž uzticību starp divām vai vairākām personām un pārliecību, ka konkrēta lieta noteikti notiks. JavaScript valodā solījums ir objekts, kas nodrošina vienas vērtības radīšanu nākotnē (ja nepieciešams). Promise JavaScript tiek izmantots, lai pārvaldītu un risinātu asinhronās darbības.

Solījums atgriež objektu, kas nodrošina un atspoguļo asinhrono darbību pabeigšanu vai kļūmi un tās izvadi. Tas ir vērtības starpniekserveris, nezinot precīzu izvadi. Tas ir noderīgi asinhronām darbībām, lai nodrošinātu iespējamo veiksmes vērtību vai neveiksmes iemeslu. Tādējādi asinhronās metodes atgriež vērtības kā sinhrono metodi.

Parasti solījumiem ir šādi trīs stāvokļi:

  • Izpildīts: izpildītais stāvoklis ir tad, kad lietotā darbība ir atrisināta vai veiksmīgi pabeigta.
  • Gaida: statuss Gaida ir tad, kad pieprasījums tiek apstrādāts, un piemērotā darbība nav ne atrisināta, ne noraidīta un joprojām ir sākotnējā stāvoklī.
  • Noraidīts: Noraidītais stāvoklis ir tad, kad lietotā darbība ir noraidīta, izraisot vēlamās darbības neveiksmi. Noraidīšanas iemesls var būt jebkas, tostarp servera darbība.

Solījumu sintakse:

 let newPromise = new Promise(function(resolve, reject) { // asynchronous call is made //Resolve or reject the data }); 

Tālāk ir sniegts solījumu rakstīšanas piemērs:

Šis ir solījuma rakstīšanas piemērs.

 function getArticleData(id) { return new Promise((resolve, reject) =&gt; { setTimeout(() =&gt; { console.log(&apos;Fetching data....&apos;); resolve({ id: id, name: &apos;derik&apos; }); }, 5000); }); } getArticleData(&apos;10&apos;).then(res=&gt; console.log(res)) 

Iepriekš minētajā piemērā mēs varam redzēt, kā mēs varam efektīvi izmantot solījumus, lai veiktu pieprasījumu no servera. Varam novērot, ka koda lasāmība augstāk minētajā kodā ir palielināta nekā atzvanījumos. Promises nodrošina tādas metodes kā .then() un .catch(), kas ļauj mums apstrādāt darbības statusu veiksmes vai neveiksmes gadījumā. Mēs varam precizēt gadījumus dažādiem solījumu stāvokļiem.

Asinhronizācija/gaidīšana programmā JavaScript

Tas ir vēl viens veids, kā izvairīties no ligzdotu atzvanīšanas. Async/ Await ļauj mums daudz efektīvāk izmantot solījumus. Mēs varam izvairīties no .then() vai .catch() metodes ķēdes izmantošanas. Šīs metodes ir atkarīgas arī no atzvanīšanas funkcijām.

Async/Await var precīzi izmantot kopā ar Promise, lai uzlabotu lietojumprogrammas veiktspēju. Tā iekšēji atrisināja solījumus un nodrošināja rezultātu. Turklāt tas ir labāk lasāms nekā () vai catch () metodes.

Mēs nevaram izmantot Async/Await ar parastajām atzvanīšanas funkcijām. Lai to izmantotu, funkcija ir jāpadara asinhrona, pirms funkcijas atslēgvārda ierakstot asinhrono atslēgvārdu. Tomēr iekšēji tajā tiek izmantota arī ķēde.

Tālāk ir sniegts Async/Await piemērs:

 async function displayData() { try { const articleData = await getArticle(10); const placeData = await getPlaces(article.name); const cityData = await getCity(place) console.log(city); } catch (err) { console.log(&apos;Error: &apos;, err.message); } } displayData(); 

Lai izmantotu funkciju Async/Await, funkcija ir jānorāda ar asinhrono atslēgvārdu, un funkcijā ir jāieraksta gaidīšanas atslēgvārds. Asinhronizācija pārtrauks tās izpildi, līdz solījums tiks atrisināts vai noraidīts. Tas tiks atsākts, kad solījums tiks izpildīts. Kad tas ir atrisināts, gaidīšanas izteiksmes vērtība tiks saglabāta mainīgajā, kurā tā ir.

fizzbuzz java

Kopsavilkums:

Īsumā, mēs varam izvairīties no ligzdotiem atzvaniem, izmantojot solījumus un async/wait. Papildus tiem mēs varam izmantot arī citas pieejas, piemēram, rakstīt komentārus, un var būt noderīga arī koda sadalīšana atsevišķos komponentos. Taču mūsdienās izstrādātāji dod priekšroku async/await izmantošanai.

Secinājums:

JavaScript atzvanīšanas elle tiek saukta par situāciju, kad tiek izpildīts pārāk daudz ligzdotu atzvanīšanas funkciju. Tas samazina koda lasāmību un apkopi. Atzvanīšanas elles situācija parasti rodas, veicot asinhrono pieprasījumu operācijas, piemēram, veicot vairākus API pieprasījumus vai apstrādājot notikumus ar sarežģītām atkarībām.

Lai labāk izprastu atzvanīšanas elli JavaScript.

JavaScript visu uzskata par objektu, piemēram, virknes, masīvus un funkcijas. Tādējādi atzvanīšanas koncepcija ļauj mums nodot funkciju kā argumentu citai funkcijai. Atzvanīšanas funkcija vispirms pabeigs izpildi, un vecākfunkcija tiks izpildīta vēlāk.

Atzvanīšanas funkcijas tiek izpildītas asinhroni un ļauj kodam turpināt darboties, negaidot asinhronā uzdevuma pabeigšanu.