logo

Visszahívás Pokol a JavaScriptben

A JavaScript egy aszinkron (nem blokkoló) és egyszálú programozási nyelv, ami azt jelenti, hogy egyszerre csak egy folyamat futhat.

A programozási nyelvekben a visszahívási pokol általában a kódírás aszinkron hívásokkal történő nem hatékony módjára utal. A Végzet piramisaként is ismert.

A JavaScript visszahívási poklára olyan helyzetként hivatkozunk, amikor túl sok beágyazott visszahívási függvény kerül végrehajtásra. Csökkenti a kód olvashatóságát és karbantartását. A visszahívási pokol helyzete általában akkor fordul elő, ha aszinkron kérési műveletekkel foglalkozik, például több API-kérés vagy összetett függőségi események kezelésekor.

A JavaScript visszahívási poklának jobb megértéséhez először ismerje meg a visszahívásokat és az eseményhurkokat a JavaScriptben.

Visszahívások JavaScriptben

A JavaScript mindent objektumnak tekint, például karakterláncokat, tömböket és függvényeket. Ezért a visszahívási koncepció lehetővé teszi, hogy a függvényt argumentumként adjuk át egy másik függvénynek. A visszahívási funkció előbb fejezi be a végrehajtást, később a szülő függvény.

A visszahívási funkciók aszinkron módon futnak, és lehetővé teszik a kód futtatását anélkül, hogy megvárnák az aszinkron feladat befejezését. Ha több aszinkron feladatot kombinálunk, és mindegyik feladat az előző feladattól függ, a kódstruktúra bonyolulttá válik.

Ismerjük meg a visszahívások használatát és fontosságát. Tegyük fel, hogy van egy olyan függvény, amely három paramétert, egy karakterláncot és két számot vesz fel. A karakterlánc-szöveg alapján szeretnénk valamilyen kimenetet több feltétellel.

Tekintsük az alábbi példát:

 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)) 

Kimenet:

 30 20 

A fenti kód jól működik, de további feladatokat kell adnunk ahhoz, hogy a kód méretezhető legyen. A feltételes utasítások száma is folyamatosan növekszik, ami zavaros kódszerkezethez vezet, amelyet optimalizálni és olvashatóan kell fejleszteni.

Tehát a kódot jobb módon átírhatjuk a következőképpen:

 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)) 

Kimenet:

 30 20 

Ennek ellenére a kimenet ugyanaz lesz. A fenti példában azonban meghatároztuk annak különálló függvénytörzsét, és a függvényt visszahívási függvényként adtuk át a várt eredmény függvénynek. Így, ha a várt eredmények funkcionalitását ki akarjuk terjeszteni, hogy egy másik, más művelettel működő törzset hozzunk létre, és azt visszahívási függvényként használjuk, akkor könnyebben érthetővé és javíthatóvá válik a kód olvashatósága.

A támogatott JavaScript-funkciókban más példák is találhatók a visszahívásokra. Néhány gyakori példa az eseményfigyelők és a tömbfunkciók, például a leképezés, kicsinyítés, szűrés stb.

A jobb megértéshez meg kell értenünk a JavaScript áthaladási értékét és áthaladási hivatkozását.

dhl jelentése

A JavaScript kétféle adattípust támogat: primitív és nem primitív. A primitív adattípusok definiálatlanok, nullák, karakterláncok és logikai értékek, amelyek nem változtathatók, vagy mondhatjuk, hogy összehasonlíthatatlanok; A nem primitív adattípusok tömbök, függvények és objektumok, amelyek megváltoztathatók vagy módosíthatók.

A Hivatkozás megadása átadja egy entitás hivatkozási címét, akárcsak egy függvény argumentumnak tekinthető. Tehát, ha a függvényen belüli érték megváltozik, az megváltoztatja az eredeti értéket, amely a függvényen kívül elérhető.

Összehasonlításképpen a pass-by value koncepció nem változtatja meg eredeti értékét, amely a függvénytörzsön kívül elérhető. Ehelyett a memória használatával két különböző helyre másolja az értéket. A JavaScript az összes objektumot a hivatkozásuk alapján azonosította.

A JavaScriptben az addEventListener figyeli az eseményeket, például a kattintást, az egérmutatót és az egérkilépést, és a második argumentumot veszi fel függvényként, amely az esemény aktiválása után kerül végrehajtásra. Ezt a függvényt hivatkozásonként és zárójel nélkül adjuk át.

Tekintsük az alábbi példát; ebben a példában egy üdvözlő függvényt adtunk át argumentumként az addEventListener-be visszahívási függvényként. A rendszer akkor hívja meg, amikor a kattintási esemény elindul:

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) 

Kimenet:

Visszahívás Pokol a JavaScriptben

A fenti példában egy üdvözlő függvényt adtunk át argumentumként az addEventListener-be visszahívási függvényként. A rendszer akkor hívja meg, amikor a kattintási esemény elindul.

Hasonlóképpen, a szűrő is egy példa a visszahívási funkcióra. Ha szűrőt használunk egy tömb iterálására, akkor egy másik visszahívási függvényt vesz igénybe argumentumként a tömb adatainak feldolgozásához. Tekintsük az alábbi példát; ebben a példában a nagyobb függvényt használjuk az 5-nél nagyobb szám kinyomtatására a tömbben. Az isGreater függvényt visszahívási függvényként használjuk a szűrőmódszerben.

 const arr = [3,10,6,7] const isGreater = num =&gt; num &gt; 5 console.log(arr.filter(isGreater)) 

Kimenet:

java karakterlánc elválasztóval osztott
 [ 10, 6, 7 ] 

A fenti példa azt mutatja, hogy a nagyobb függvényt visszahívási függvényként használják a szűrőmódszerben.

A visszahívások, az eseményhurkok jobb megértése érdekében a JavaScriptben, beszéljük meg a szinkron és az aszinkron JavaScriptet:

Szinkron JavaScript

Nézzük meg, melyek a szinkron programozási nyelv jellemzői. A szinkron programozás a következő tulajdonságokkal rendelkezik:

A végrehajtás blokkolása: A szinkron programozási nyelv támogatja a blokkoló végrehajtási technikát, ami azt jelenti, hogy blokkolja a következő utasítások végrehajtását, a meglévő utasítások végrehajtásra kerülnek. Így az utasítások kiszámítható és determinisztikus végrehajtását biztosítja.

Szekvenciális áramlás: A szinkron programozás támogatja a szekvenciális végrehajtási folyamatot, ami azt jelenti, hogy minden utasítás szekvenciális módon, egymás után kerül végrehajtásra. A nyelvi program megvárja egy utasítás befejezését, mielőtt a következőre lépne.

Egyszerűség: A szinkron programozást gyakran könnyen érthetőnek tekintik, mert meg tudjuk jósolni a végrehajtási folyamat sorrendjét. Általában lineáris és könnyen megjósolható. A kis alkalmazásokat jó ezeken a nyelveken fejleszteni, mert képesek kezelni a műveletek kritikus sorrendjét.

watchcartoononline.io alternatívák

Közvetlen hibakezelés: Szinkron programozási nyelvben a hibakezelés nagyon egyszerű. Ha hiba történik egy utasítás végrehajtása közben, az hibát dob, és a program elkaphatja.

Dióhéjban a szinkron programozásnak két alapvető funkciója van, azaz egyszerre egyetlen feladatot hajtanak végre, és a következő feladatok csak akkor lesznek kezelve, ha az aktuális feladat befejeződik. Ezáltal szekvenciális kódvégrehajtást követ.

A programozásnak ez a viselkedése utasítás végrehajtása közben, a nyelv blokkkód helyzetet hoz létre, mivel minden feladatnak meg kell várnia az előző feladat befejezését.

De amikor az emberek a JavaScriptről beszélnek, mindig rejtélyes válasz volt, hogy az szinkron vagy aszinkron.

A fent tárgyalt példákban, amikor egy függvényt visszahívásként használtunk a szűrőfüggvényben, az szinkronban futott. Ezért nevezik szinkron végrehajtásnak. A szűrő függvénynek meg kell várnia, hogy a nagyobb függvény befejezze a végrehajtását.

Ezért a visszahívási függvényt visszahívások blokkolásának is nevezik, mivel blokkolja annak a szülőfüggvénynek a végrehajtását, amelyben meghívták.

A JavaScriptet elsősorban egyszálú szinkronnak és blokkoló jellegűnek tekintik. Néhány megközelítéssel azonban aszinkron módon működhet a különböző forgatókönyvek alapján.

Most pedig értsük meg az aszinkron JavaScriptet.

Aszinkron JavaScript

Az aszinkron programozási nyelv az alkalmazás teljesítményének javítására összpontosít. A visszahívások ilyen esetekben használhatók. Az alábbi példával elemezhetjük a JavaScript aszinkron viselkedését:

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

A fenti példából a setTimeout függvény egy visszahívást és az időt ezredmásodpercben veszi fel argumentumként. A visszahívás a megadott idő (itt 1s) után kerül meghívásra. Dióhéjban, a függvény 1 másodpercig vár a végrehajtásra. Most nézze meg az alábbi kódot:

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

Kimenet:

 first Second greet after 1 second 

A fenti kódból a setTimeout utáni naplóüzenetek kerülnek először végrehajtásra, miközben az időzítő elhalad. Így ez egy másodpercet, majd 1 másodperces időintervallum után az üdvözlő üzenetet eredményezi.

A JavaScriptben a setTimeout egy aszinkron függvény. Amikor meghívjuk a setTimeout függvényt, az egy visszahívási függvényt (jelen esetben üdvözletet) regisztrál, amelyet a megadott késleltetés után kell végrehajtani. Ez azonban nem blokkolja a következő kód végrehajtását.

A fenti példában a naplóüzenetek azok a szinkron utasítások, amelyek azonnal végrehajtódnak. Nem függenek a setTimeout függvénytől. Ezért végrehajtják és naplózzák a megfelelő üzeneteiket a konzolon anélkül, hogy megvárnák a setTimeout-ban megadott késleltetést.

Eközben a JavaScript eseményhuroka kezeli az aszinkron feladatokat. Ilyenkor megvárja a megadott késleltetés (1 másodperc) letelését, majd ennek letelte után felveszi a visszahívási funkciót (köszön) és végrehajtja azt.

Így a setTimeout függvény utáni másik kód a háttérben futott. Ez a viselkedés lehetővé teszi, hogy a JavaScript más feladatokat hajtson végre, miközben az aszinkron művelet befejezésére vár.

Meg kell értenünk a hívásveremet és a visszahívási sort az aszinkron események JavaScriptben történő kezeléséhez.

Vegye figyelembe az alábbi képet:

Visszahívás Pokol a JavaScriptben

A fenti kép alapján egy tipikus JavaScript-motor egy kupac memóriából és egy hívásveremből áll. A hívási verem várakozás nélkül végrehajtja az összes kódot, amikor a verembe kerül.

A kupacmemória felelős a memória lefoglalásáért az objektumok és funkciók számára futás közben, amikor csak szükség van rájuk.

Böngészőmotorjaink jelenleg több webes API-ból állnak, például DOM, setTimeout, console, fetch stb., és a motor hozzáférhet ezekhez az API-khoz a globális ablak objektum segítségével. A következő lépésben néhány eseményhurok a kapuőr szerepét tölti be, amely kiválasztja a függvénykéréseket a visszahívási sorban, és a verembe tolja azokat. Ezek a funkciók, mint például a setTimeout, bizonyos várakozási időt igényelnek.

Most térjünk vissza példánkhoz, a setTimeout függvényhez; Amikor a függvény találkozik, az időzítő bekerül a visszahívási sorba. Ezt követően a kód többi része a hívási verembe kerül, és akkor kerül végrehajtásra, amikor a függvény eléri az időzítő korlátját, lejár, és a visszahívási sor megnyomja a megadott logikával rendelkező és az időtúllépési függvényben regisztrált visszahívási függvényt. . Így a megadott idő után végrehajtódik.

Visszahívás a pokol forgatókönyvei

Most megvitattuk a visszahívásokat, a szinkront, az aszinkront és más releváns témákat a visszahívási pokolhoz. Nézzük meg, mi a visszahívási pokol a JavaScriptben.

jgombot

Azt a helyzetet, amikor több visszahívás van egymásba ágyazva, visszahívási pokolnak nevezik, mivel a kód alakja piramisnak tűnik, amelyet a „végzet piramisának” is neveznek.

A visszahívási pokol megnehezíti a kód megértését és karbantartását. Leginkább a JS csomópontban való munka közben láthatjuk ezt a helyzetet. Vegyük például az alábbi példát:

 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... } }) 

A fenti példában a getUserData olyan felhasználónevet vesz fel, amely a cikklistától függ, vagy ki kell bontani a cikkben található getArticles választ. A getAddress is hasonló függőséggel rendelkezik, amely a getUserData válaszától függ. Ezt a helyzetet hívják visszahívási pokolnak.

A visszahívási pokol belső működése az alábbi példával érthető meg:

Értsük meg, hogy végre kell hajtanunk az A feladatot. Egy feladat végrehajtásához szükségünk van néhány adatra a B feladatból. Hasonlóan; különböző feladataink vannak, amelyek egymástól függőek és aszinkron módon hajtódnak végre. Így egy sor visszahívási függvényt hoz létre.

Ismerjük meg a JavaScript ígéreteit, és azt, hogyan hoznak létre aszinkron műveleteket, amelyek lehetővé teszik számunkra, hogy elkerüljük a beágyazott visszahívások írását.

JavaScript ígér

JavaScriptben az ígéreteket az ES6-ban vezették be. Ez egy szintaktikai bevonattal ellátott tárgy. Aszinkron viselkedése miatt ez egy alternatív módja annak, hogy elkerüljük az aszinkron műveletek visszahívásait. Napjainkban az olyan webes API-k, mint a fetch(), az ígéretes használatával valósulnak meg, amely hatékony módot biztosít az adatokhoz a szerverről. A kód olvashatóságát is javította, és ezzel elkerülhető a beágyazott visszahívások írása.

mylivericket

A való életben tett ígéretek bizalmat fejeznek ki két vagy több személy között, és annak biztosítékát, hogy egy adott dolog biztosan meg fog történni. A JavaScriptben az ígéret egy olyan objektum, amely egyetlen érték előállítását biztosítja a jövőben (ha szükséges). A JavaScript Promise az aszinkron műveletek kezelésére és kezelésére szolgál.

Az ígéret egy olyan objektumot ad vissza, amely biztosítja és reprezentálja az aszinkron műveletek befejezését vagy meghibásodását, valamint annak kimenetét. Ez egy érték proxyja a pontos kimenet ismerete nélkül. Hasznos az aszinkron műveleteknél, hogy megadja a végső sikerértéket vagy a kudarc okát. Így az aszinkron metódusok úgy adják vissza az értékeket, mint egy szinkron metódus.

Általában az ígéretek a következő három állapottal rendelkeznek:

  • Teljesült: A teljesült állapot az, amikor az alkalmazott műveletet sikeresen megoldották vagy befejezték.
  • Függőben: a Függőben állapot az, amikor a kérés folyamatban van, és az alkalmazott műveletet még nem sikerült megoldani vagy elutasítani, és még mindig a kezdeti állapotában van.
  • Elutasítva: Az elutasított állapot az, amikor az alkalmazott műveletet elutasították, ami a kívánt művelet meghiúsulását okozza. Az elutasítás oka bármi lehet, beleértve a szerver leállását is.

Az ígéretek szintaxisa:

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

Az alábbiakban egy példa az ígéretek írására:

Ez egy példa az ígéret írására.

 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)) 

A fenti példában láthatjuk, hogyan tudjuk hatékonyan felhasználni az ígéreteket a szervertől érkező kérésekhez. Megfigyelhető, hogy a kód olvashatósága nagyobb a fenti kódban, mint a visszahívásoknál. A Promises olyan metódusokat biztosít, mint a .then() és a .catch(), amelyek lehetővé teszik a műveleti állapot kezelését siker vagy kudarc esetén. Meghatározhatjuk az eseteket az ígéretek különböző állapotaihoz.

Async/Await JavaScriptben

Ez egy másik módja a beágyazott visszahívások elkerülésének. Az Async/ Await lehetővé teszi az ígéretek sokkal hatékonyabb felhasználását. Elkerülhetjük a .then() vagy .catch() metódusok láncolását. Ezek a módszerek a visszahívási funkcióktól is függenek.

Az Async/Await pontosan használható a Promise-val az alkalmazás teljesítményének javítására. Belsőleg megoldotta az ígéreteket, és meg is hozta az eredményt. Ezenkívül ismét olvashatóbb, mint a () vagy a catch() metódus.

Nem tudjuk használni az Async/Await funkciót a normál visszahívási funkciókkal. Használatához egy függvényt aszinkronná kell tennünk úgy, hogy a függvény kulcsszó elé írunk egy aszinkron kulcsszót. Belsőleg azonban láncolást is használ.

Az alábbiakban egy példa az Async/Await funkcióra:

 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(); 

Az Async/Await használatához a függvényt az async kulcsszóval kell megadni, az await kulcsszót pedig a függvénybe kell írni. Az async leállítja a végrehajtását, amíg az ígéretet meg nem oldják vagy el nem utasítják. Az ígéret teljesítése után folytatódik. A megoldást követően a await kifejezés értéke az azt tartó változóban tárolódik.

Összegzés:

Dióhéjban, elkerülhetjük a beágyazott visszahívásokat az ígéretek és az async/await használatával. Ezeken kívül más megközelítéseket is követhetünk, például megjegyzéseket írhatunk, és a kód különálló komponensekre bontása is hasznos lehet. De manapság a fejlesztők előnyben részesítik az async/await használatát.

Következtetés:

A JavaScript visszahívási poklára olyan helyzetként hivatkozunk, amikor túl sok beágyazott visszahívási függvény kerül végrehajtásra. Csökkenti a kód olvashatóságát és karbantartását. A visszahívási pokol helyzete általában akkor fordul elő, ha aszinkron kérési műveletekkel foglalkozik, például több API-kérés vagy összetett függőségi események kezelésekor.

Hogy jobban megértsük a visszahívási poklot a JavaScriptben.

A JavaScript mindent objektumnak tekint, például karakterláncokat, tömböket és függvényeket. Ezért a visszahívási koncepció lehetővé teszi, hogy a függvényt argumentumként adjuk át egy másik függvénynek. A visszahívási funkció előbb fejezi be a végrehajtást, később a szülő függvény.

A visszahívási funkciók aszinkron módon futnak, és lehetővé teszik a kód futtatását anélkül, hogy megvárnák az aszinkron feladat befejezését.