„JavaScript“ yra asinchroninė (neblokuojanti) ir vienos gijos programavimo kalba, tai reiškia, kad vienu metu galima vykdyti tik vieną procesą.
Programavimo kalbose atgalinio ryšio pragaras paprastai reiškia neveiksmingą kodo rašymo būdą naudojant asinchroninius skambučius. Jis taip pat žinomas kaip Pražūties piramidė.
„JavaScript“ atgalinio skambinimo pragaras vadinamas situacija, kai vykdoma per daug įdėtųjų atgalinio skambinimo funkcijų. Tai sumažina kodo skaitomumą ir priežiūrą. Atšaukimo pragaro situacija paprastai įvyksta atliekant asinchronines užklausų operacijas, pvz., pateikiant kelias API užklausas arba tvarkant įvykius su sudėtingomis priklausomybėmis.
Norėdami geriau suprasti „JavaScript“ atšaukimo pragarą, pirmiausia supraskite „JavaScript“ atgalinius skambučius ir įvykių ciklus.
Atgaliniai skambučiai „JavaScript“.
„JavaScript“ viską laiko objektu, pvz., eilutes, masyvus ir funkcijas. Taigi atgalinio ryšio koncepcija leidžia mums perduoti funkciją kaip argumentą kitai funkcijai. Atšaukimo funkcija pirmiausia užbaigs vykdymą, o pirminė funkcija bus vykdoma vėliau.
Atgalinio skambinimo funkcijos vykdomos asinchroniškai ir leidžia kodui toliau veikti nelaukiant, kol bus atlikta asinchroninė užduotis. Kai sujungiamos kelios asinchroninės užduotys, o kiekviena priklauso nuo ankstesnės užduoties, kodo struktūra tampa sudėtinga.
Supraskime atgalinių skambučių naudojimą ir svarbą. Tarkime, kad pavyzdyje turime funkciją, kuri apima tris parametrus, vieną eilutę ir du skaičius. Norime išvesties pagal eilutės tekstą su keliomis sąlygomis.
Apsvarstykite toliau pateiktą pavyzdį:
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))
Išvestis:
30 20
Aukščiau pateiktas kodas veiks gerai, tačiau turime pridėti daugiau užduočių, kad kodą būtų galima keisti. Sąlyginių teiginių skaičius taip pat nuolat didės, o tai sukels nepatogią kodo struktūrą, kurią reikia optimizuoti ir skaityti.
Taigi, kodą galime perrašyti geresniu būdu taip:
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))
Išvestis:
30 20
Vis dėlto išeiga bus tokia pati. Tačiau aukščiau pateiktame pavyzdyje apibrėžėme atskirą jos funkcijos turinį ir perdavėme funkciją kaip atgalinio skambinimo funkciją numatytai rezultato funkcijai. Taigi, jei norime išplėsti laukiamų rezultatų funkcionalumą, kad galėtume sukurti kitą veikiantį elementą su kita operacija ir panaudoti jį kaip atgalinio skambinimo funkciją, bus lengviau suprasti ir pagerinti kodo skaitomumą.
Palaikomose „JavaScript“ funkcijose yra ir kitų skirtingų atgalinių skambučių pavyzdžių. Keletas įprastų pavyzdžių yra įvykių klausytojai ir masyvo funkcijos, pvz., žemėlapis, mažinimas, filtravimas ir kt.
Kad geriau suprastume, turėtume suprasti „JavaScript“ reikšmę ir nuorodas.
„JavaScript“ palaiko dviejų tipų duomenų tipus – primityvius ir neprimityvius. Primityvūs duomenų tipai yra neapibrėžti, nuliniai, eilutės ir loginiai, kurių negalima pakeisti arba galime sakyti, kad jie yra nekintami; Neprimityvūs duomenų tipai yra masyvai, funkcijos ir objektai, kuriuos galima keisti arba keisti.
Perdavimas pagal nuorodą perduoda objekto nuorodos adresą, kaip ir funkcija gali būti laikoma argumentu. Taigi, jei tos funkcijos reikšmė bus pakeista, ji pakeis pradinę reikšmę, kuri pasiekiama už funkcijos ribų.
Palyginimui, praeinančios vertės koncepcija nekeičia savo pradinės vertės, kuri pasiekiama už funkcijos korpuso ribų. Vietoj to, ji nukopijuos vertę į dvi skirtingas vietas naudodama jų atmintį. „JavaScript“ identifikavo visus objektus pagal jų nuorodą.
„JavaScript“ programoje „addEventListener“ klausosi įvykių, pvz., paspaudimo, pelės žymeklio užvedimo ir pelės pašalinimo, ir antrąjį argumentą priima kaip funkciją, kuri bus vykdoma suaktyvinus įvykį. Ši funkcija naudojama pagal nuorodos sąvoką ir perduodama be skliaustų.
Apsvarstykite toliau pateiktą pavyzdį; Šiame pavyzdyje mes perdavėme pasveikinimo funkciją kaip argumentą į addEventListener kaip atgalinio skambinimo funkciją. Jis bus iškviestas, kai suaktyvinamas paspaudimo įvykis:
Test.html:
Javascript Callback Example <h3>Javascript Callback</h3> Click Here to Console const button = document.getElementById('btn'); const greet=()=>{ console.log('Hello, How are you?') } button.addEventListener('click', greet)
Išvestis:
Aukščiau pateiktame pavyzdyje mes perdavėme pasveikinimo funkciją kaip argumentą į addEventListener kaip atgalinio skambinimo funkciją. Jis bus iškviestas, kai suaktyvinamas paspaudimo įvykis.
Panašiai filtras taip pat yra atgalinio skambinimo funkcijos pavyzdys. Jei masyvo kartojimui naudosime filtrą, masyvo duomenims apdoroti kaip argumentą bus naudojama kita atgalinio skambinimo funkcija. Apsvarstykite toliau pateiktą pavyzdį; Šiame pavyzdyje mes naudojame didesnę funkciją norėdami atspausdinti didesnį nei 5 skaičių masyve. Mes naudojame funkciją isGreater kaip atgalinio skambinimo funkciją filtro metodu.
const arr = [3,10,6,7] const isGreater = num => num > 5 console.log(arr.filter(isGreater))
Išvestis:
[ 10, 6, 7 ]
Aukščiau pateiktame pavyzdyje parodyta, kad didesnė funkcija naudojama kaip atgalinio skambinimo funkcija filtro metodu.
Norėdami geriau suprasti „JavaScript“ skambučius, įvykių kilpas, aptarkime sinchroninį ir asinchroninį „JavaScript“:
Sinchroninis JavaScript
Supraskime, kokios yra sinchroninio programavimo kalbos savybės. Sinchroninis programavimas turi šias funkcijas:
Vykdymo blokavimas: Sinchroninio programavimo kalba palaiko blokavimo vykdymo techniką, o tai reiškia, kad ji blokuoja tolesnių teiginių vykdymą, o esami sakiniai bus vykdomi. Taip pasiekiamas nuspėjamas ir deterministinis teiginių vykdymas.
Nuoseklus srautas: Sinchroninis programavimas palaiko nuoseklų vykdymo srautą, o tai reiškia, kad kiekvienas sakinys vykdomas nuosekliai, kaip vienas po kito. Kalbos programa laukia, kol pareiškimas bus baigtas, prieš pereidama prie kito.
Paprastumas: Dažnai sinchroninis programavimas laikomas lengvai suprantamu, nes galime numatyti jo vykdymo eigos tvarką. Paprastai tai yra linijinė ir lengvai nuspėjama. Mažas programas verta kurti šiomis kalbomis, nes jos gali susidoroti su kritine operacijų tvarka.
Tiesioginis klaidų tvarkymas: Sinchroninėje programavimo kalboje klaidų tvarkymas yra labai paprastas. Jei vykdant sakinį įvyksta klaida, ji išmes klaidą ir programa gali ją užfiksuoti.
Trumpai tariant, sinchroninis programavimas turi dvi pagrindines funkcijas, t. y. vienu metu vykdoma viena užduotis, o kitas sekančių užduočių rinkinys bus sprendžiamas tik tada, kai dabartinė užduotis bus baigta. Taigi jis seka nuoseklų kodo vykdymą.
Toks programavimo elgesys, kai vykdomas sakinys, kalba sukuria blokinio kodo situaciją, nes kiekviena užduotis turi laukti, kol bus atlikta ankstesnė užduotis.
Tačiau kai žmonės kalba apie „JavaScript“, tai visada buvo mįslingas atsakymas, ar jis sinchroninis, ar asinchroninis.
Aukščiau aptartuose pavyzdžiuose, kai filtro funkcijoje naudojome funkciją kaip atgalinį skambutį, ji buvo vykdoma sinchroniškai. Todėl jis vadinamas sinchroniniu vykdymu. Filtro funkcija turi palaukti, kol didesnė funkcija baigs vykdyti.
Taigi atgalinio skambinimo funkcija taip pat vadinama blokuojančia atgalinius skambučius, nes ji blokuoja pagrindinės funkcijos, kuriai ji buvo iškviesta, vykdymą.
Visų pirma, „JavaScript“ yra laikomas vienos gijos sinchroniniu ir blokuojančiu pobūdžiu. Tačiau taikydami kelis metodus galime priversti jį veikti asinchroniškai pagal skirtingus scenarijus.
Dabar supraskime asinchroninį „JavaScript“.
Asinchroninis JavaScript
Asinchroninė programavimo kalba skirta programos našumui pagerinti. Tokiais atvejais galima naudoti atgalinius skambučius. Mes galime analizuoti asinchroninį JavaScript elgesį pagal toliau pateiktą pavyzdį:
function greet(){ console.log('greet after 1 second') } setTimeout(greet, 1000)
Aukščiau pateiktame pavyzdyje funkcija setTimeout kaip argumentus priima atgalinį skambutį ir laiką milisekundėmis. Atgalinis skambutis iškviečiamas praėjus nurodytam laikui (čia 1 s). Trumpai tariant, funkcija palauks 1 s, kol ji bus įvykdyta. Dabar pažvelkite į toliau pateiktą kodą:
function greet(){ console.log('greet after 1 second') } setTimeout(greet, 1000) console.log('first') console.log('Second')
Išvestis:
first Second greet after 1 second
Iš aukščiau pateikto kodo žurnalo pranešimai po setTimeout bus vykdomi pirmiausia, o laikmatis praeis. Vadinasi, po vienos sekundės gaunamas pasisveikinimo pranešimas, po 1 sekundės laiko intervalo.
„JavaScript“ programoje setTimeout yra asinchroninė funkcija. Kai iškviečiame funkciją setTimeout, ji užregistruoja atgalinio skambučio funkciją (šiuo atveju sveikinimą), kuri turi būti vykdoma po nurodyto delsos. Tačiau tai neblokuoja tolesnio kodo vykdymo.
Pirmiau pateiktame pavyzdyje žurnalo pranešimai yra sinchroniniai teiginiai, kurie vykdomi nedelsiant. Jie nepriklauso nuo setTimeout funkcijos. Todėl jie vykdo ir registruoja atitinkamus pranešimus konsolėje, nelaukdami setTimeout nurodytos delsos.
Tuo tarpu „JavaScript“ įvykių ciklas tvarko asinchronines užduotis. Tokiu atveju jis laukia, kol praeis nurodyta delsa (1 sekundė), o praėjus šiam laikui paima atgalinio skambučio funkciją (sveikinimą) ir ją vykdo.
Taigi kitas kodas po setTimeout funkcijos buvo vykdomas veikiant fone. Šis elgesys leidžia „JavaScript“ atlikti kitas užduotis laukiant, kol bus baigta asinchroninė operacija.
Turime suprasti skambučių krūvą ir atgalinio skambinimo eilę, kad galėtume tvarkyti asinchroninius įvykius „JavaScript“.
Apsvarstykite toliau pateiktą vaizdą:
Aukščiau pateiktame paveikslėlyje tipiškas „JavaScript“ variklis susideda iš krūvos atminties ir skambučių krūvos. Skambučių krūva vykdo visą kodą nelaukdama, kai nustumiama į krūvą.
Krūvos atmintis yra atsakinga už atminties paskirstymą objektams ir funkcijoms vykdymo metu, kai jų reikia.
Dabar mūsų naršyklės variklius sudaro kelios žiniatinklio API, pvz., DOM, setTimeout, konsolė, gavimas ir kt., o variklis gali pasiekti šias API naudodamas visuotinio lango objektą. Kitame veiksme kai kurios įvykių kilpos atlieka vartų prižiūrėtojo vaidmenį, kuris atrenka funkcijų užklausas atgalinio skambinimo eilėje ir nustumia jas į krūvą. Šios funkcijos, pvz., setTimeout, reikalauja tam tikro laukimo laiko.
Dabar grįžkime prie mūsų pavyzdžio – funkcijos setTimeout; Kai funkcija aptinkama, laikmatis užregistruojamas atgalinio skambinimo eilėje. Po to likusi kodo dalis nustumiama į skambučių krūvą ir vykdoma, kai funkcija pasiekia laikmačio ribą, pasibaigia jos galiojimo laikas, o atgalinio skambinimo eilė stumia atgalinio skambinimo funkciją, kuri turi nurodytą logiką ir yra užregistruota skirtojo laiko funkcijoje. . Taigi jis bus įvykdytas po nurodyto laiko.
sudėtinis pirminis raktas
Atšaukimo pragaro scenarijai
Dabar aptarėme atgalinius skambučius, sinchroninius, asinchroninius ir kitas aktualias atgalinio pragaro temas. Supraskime, kas yra „JavaScript“ atgalinio skambučio pragaras.
Situacija, kai įterpiami keli atgaliniai skambučiai, vadinama atgalinio skambučio pragaru, nes jo kodo forma atrodo kaip piramidė, kuri dar vadinama „pasmerkimo piramide“.
Atšaukimo pragaras apsunkina kodo supratimą ir priežiūrą. Dažniausiai šią situaciją matome dirbdami mazge JS. Pavyzdžiui, apsvarstykite toliau pateiktą pavyzdį:
getArticlesData(20, (articles) => { console.log('article lists', articles); getUserData(article.username, (name) => { console.log(name); getAddress(name, (item) => { console.log(item); //This goes on and on... } })
Aukščiau pateiktame pavyzdyje „getUserData“ paima vartotojo vardą, kuris priklauso nuo straipsnių sąrašo arba turi būti ištrauktas „getArticles“ atsakymas, esantis straipsnyje. getAddress taip pat turi panašią priklausomybę, kuri priklauso nuo getUserData atsakymo. Ši situacija vadinama atgalinio pragaru.
Vidinį atgalinio pragaro veikimą galima suprasti pagal toliau pateiktą pavyzdį:
Supraskime, kad turime atlikti užduotį A. Norėdami atlikti užduotį, mums reikia kai kurių duomenų iš užduoties B. Panašiai; turime skirtingas užduotis, kurios priklauso viena nuo kitos ir vykdomos asinchroniškai. Taigi sukuriama daugybė atgalinio ryšio funkcijų.
Supraskime „JavaScript“ pažadus ir kaip jie sukuria asinchronines operacijas, leidžiančias nerašyti įdėtųjų atgalinių skambučių.
„JavaScript“ pažadai
„JavaScript“ pažadai buvo pristatyti ES6. Tai objektas su sintaksine danga. Dėl asinchroninio elgesio tai yra alternatyvus būdas išvengti asinchroninių operacijų atgalinių skambučių rašymo. Šiais laikais žiniatinklio API, pvz., fetch(), yra įdiegtos naudojant perspektyvųjį, kuris suteikia veiksmingą būdą pasiekti duomenis iš serverio. Tai taip pat pagerino kodo skaitomumą ir yra būdas išvengti įdėtųjų atgalinių skambučių rašymo.
Pažadai realiame gyvenime išreiškia pasitikėjimą tarp dviejų ar daugiau asmenų ir užtikrinimą, kad konkretus dalykas tikrai įvyks. „JavaScript“ programoje pažadas yra objektas, užtikrinantis, kad ateityje būtų sukurta viena vertė (kai to reikia). „JavaScript“ pažadas naudojamas asinchroninėms operacijoms valdyti ir spręsti.
Pažadas grąžina objektą, kuris užtikrina ir atspindi asinchroninių operacijų užbaigimą arba nesėkmę ir jos išvestį. Tai vertės tarpinis serveris, nežinant tikslios išvesties. Tai naudinga asinchroniniams veiksmams, norint pateikti galutinę sėkmės vertę arba nesėkmės priežastį. Taigi asinchroniniai metodai grąžina reikšmes kaip sinchroninis metodas.
Paprastai pažadai turi šias tris būsenas:
- Įvykdyta: įvykdyta būsena yra tada, kai taikomas veiksmas buvo sėkmingai išspręstas arba baigtas.
- Laukiama: būsena Laukiama, kai užklausa yra apdorojama, o taikomas veiksmas nebuvo nei išspręstas, nei atmestas ir vis dar yra pradinės būsenos.
- Atmesta: atmesta būsena, kai taikomas veiksmas buvo atmestas, todėl norima operacija nepavyksta. Atmetimo priežastis gali būti bet kokia, įskaitant serverio neveikiantį veiksmą.
Pažadų sintaksė:
let newPromise = new Promise(function(resolve, reject) { // asynchronous call is made //Resolve or reject the data });
Žemiau pateikiamas pažadų rašymo pavyzdys:
Tai yra pažado rašymo pavyzdys.
function getArticleData(id) { return new Promise((resolve, reject) => { setTimeout(() => { console.log('Fetching data....'); resolve({ id: id, name: 'derik' }); }, 5000); }); } getArticleData('10').then(res=> console.log(res))
Aukščiau pateiktame pavyzdyje matome, kaip galime efektyviai panaudoti pažadus, kad pateiktume užklausą iš serverio. Galime pastebėti, kad aukščiau pateiktame kode kodo skaitomumas yra didesnis nei atgalinių skambučių. Pažadai pateikia tokius metodus kaip .then() ir .catch(), kurie leidžia tvarkyti operacijos būseną sėkmės ar nesėkmės atveju. Galime nurodyti skirtingų pažadų būsenų atvejus.
Asinchronizavimas / laukimas „JavaScript“.
Tai dar vienas būdas išvengti įdėtųjų atgalinių skambučių naudojimo. Async/ Await leidžia mums daug efektyviau panaudoti pažadus. Galime nenaudoti .then() arba .catch() metodų grandinės. Šie metodai taip pat priklauso nuo atgalinio skambinimo funkcijų.
Async/Await galima tiksliai naudoti kartu su Promise, siekiant pagerinti programos veikimą. Ji viduje išsprendė pažadus ir pateikė rezultatą. Be to, vėlgi, jis yra geriau skaitomas nei () arba catch () metodai.
Negalime naudoti Async / Await su įprastomis atgalinio skambinimo funkcijomis. Norėdami jį naudoti, turime padaryti funkciją asinchroninę, prieš funkcijos raktinį žodį parašydami asinchroninį raktinį žodį. Tačiau viduje jis taip pat naudoja grandinėjimą.
Žemiau pateikiamas Async / Await pavyzdys:
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('Error: ', err.message); } } displayData();
Norint naudoti Async/Await, funkcija turi būti nurodyta su async raktiniu žodžiu, o laukimo raktinis žodis turi būti įrašytas funkcijos viduje. Asinchronizacija nustos vykdyti tol, kol pažadas bus išspręstas arba atmestas. Jis bus atnaujintas, kai bus įvykdytas pažadas. Išsprendus laukimo išraiškos reikšmė bus išsaugota ją turinčiame kintamajame.
Santrauka:
Trumpai tariant, galime išvengti įdėtų atgalinių skambučių naudodami pažadus ir async/laukti. Be šių, galime vadovautis ir kitais būdais, pavyzdžiui, rašyti komentarus, o kodo padalijimas į atskirus komponentus taip pat gali būti naudingas. Tačiau šiais laikais kūrėjai renkasi async/wait naudojimą.
Išvada:
„JavaScript“ atgalinio skambinimo pragaras vadinamas situacija, kai vykdoma per daug įdėtųjų atgalinio skambinimo funkcijų. Tai sumažina kodo skaitomumą ir priežiūrą. Atšaukimo pragaro situacija paprastai įvyksta atliekant asinchronines užklausų operacijas, pvz., pateikiant kelias API užklausas arba tvarkant įvykius su sudėtingomis priklausomybėmis.
Norėdami geriau suprasti „JavaScript“ atšaukimo pragarą.
„JavaScript“ viską laiko objektu, pvz., eilutes, masyvus ir funkcijas. Taigi atgalinio ryšio koncepcija leidžia mums perduoti funkciją kaip argumentą kitai funkcijai. Atšaukimo funkcija pirmiausia užbaigs vykdymą, o pirminė funkcija bus vykdoma vėliau.
Atgalinio skambinimo funkcijos vykdomos asinchroniškai ir leidžia kodui toliau veikti nelaukiant, kol bus atlikta asinchroninė užduotis.