smyčka událostí v uzlu js

Smycka Udalosti V Uzlu Js



Node.js je výkonný Javascriptový framework, který umožňuje uživatelům spouštět Javascriptový kód na serveru mimo prohlížeč. Jedná se o neblokující běhové prostředí řízené událostmi pro vytváření spolehlivých škálovatelných webových aplikací. Smyčka událostí je důležitou součástí Node.js, která vám umožňuje provádět úkoly bez čekání na dokončení jednoho, než začnete s dalším.

Přestože je Javascript jednovláknový jazyk, Node.js může přidělovat úkoly operačnímu systému, což mu umožňuje zpracovávat více úkolů současně. Několik úkolů musí být dokončeno současně, protože operace v operačním systému jsou vícevláknové. Zpětné volání spojené s každou operací je přidáno do fronty událostí a je naplánováno Node.js tak, aby se spustilo po dokončení zadané úlohy.

Aby uživatel mohl psát efektivní a spolehlivý kód Node.js, musí dobře rozumět smyčkám událostí. Může také pomoci efektivně řešit problémy s výkonem. Smyčka událostí v Node.js šetří paměť a umožňuje vám dělat více věcí najednou, aniž byste museli čekat, až každá skončí. Termín „asynchronní“ označuje jakoukoli funkci Javascriptu, která běží na pozadí bez blokování příchozích požadavků.







Než přejdeme přímo na smyčky událostí, podívejme se na různé aspekty programovacího jazyka Javascript.



Javascript jako asynchronní programovací jazyk

Pojďme se podívat na koncepty asynchronního programování. Javascript se používá ve webových, mobilních a desktopových aplikacích, ale je třeba poznamenat, že Javascript je jednovláknový synchronní počítačový programovací jazyk.



Pro pochopení konceptu je uveden jednoduchý příklad kódu.





funkční metoda1 ( ) {

řídicí panel. log ( 'Funkce 1' )

}

funkční metoda2 ( ) {

řídicí panel. log ( 'Funkce 2' )

}

metoda1 ( )

metoda2 ( )

V tomto kódu jsou vytvořeny dvě jednoduché funkce a nejprve je volána metoda1, takže se nejprve zaznamená metoda1 a poté se přesune na další.

Výstup



Javascript jako synchronní programovací jazyk

Javascript je synchronní programovací jazyk a provádí každý řádek krok za krokem, který se pohybuje shora dolů, přičemž je současně spuštěn pouze jeden řádek. Ve výše uvedeném příkladu kódu je metoda1 nejprve přihlášena do terminálu a poté metoda2.

Javascript jako blokovací jazyk

Být synchronním jazykem javascript má funkci blokování. Nezáleží na tom, jak dlouho trvá dokončení probíhajícího procesu, ale nový proces nebude zahájen, dokud nebude dokončen ten předchozí. Ve výše uvedeném příkladu kódu předpokládejme, že v metodě1 je mnoho skriptů kódu bez ohledu na to, jak dlouho to trvá 10 sekund nebo minutu, metoda2 se nespustí, dokud nebude proveden veškerý kód v metodě1.

Uživatelé to mohli zažít při procházení. Když se webová aplikace spouští v prohlížeči na back-endu, je spouštěn obrovský kus kódu, takže prohlížeč vypadá, že je na nějakou dobu zamrzlý, než vrátí uživateli kontrolní přístup. Toto chování je známé jako blokování. Prohlížeč nemůže přijímat žádné další příchozí požadavky, dokud nebude aktuální požadavek zpracován.

Javascript je jednovláknový jazyk

Ke spuštění programu v javascriptu se používá funkce vlákna. Vlákna jsou schopna provádět pouze jeden úkol najednou. Jiné programovací jazyky podporují multi-threading a mohou spouštět více úloh paralelně, javascript obsahuje pouze jedno vlákno pro provádění libovolného kódového skriptu.

Čekání v Javascriptu

Jak je patrné z názvu v této sekci, musíme počkat na zpracování naší žádosti, abychom mohli pokračovat. Čekání může trvat několik minut, během kterých není vyřizován žádný další požadavek. Pokud skript kódu pokračuje bez čekání, kód narazí na chybu. Některé funkce mají být implementovány v Javascriptu nebo konkrétněji Node.js, aby byl kód asynchronní.

Nyní, když jsme pochopili různé aspekty Javascriptu, pojďme pochopit synchronní a asynchronní pomocí několika jednoduchých příkladů.

Synchronní provádění kódu v Javascriptu

Synchronní znamená, že kód je spouštěn postupně nebo jednodušeji krok za krokem počínaje shora a postupuje dolů řádek po řádku.

Níže je uveden příklad, který může pomoci pochopit:

// application.js

řídicí panel. log ( 'Jeden' )

řídicí panel. log ( 'Dva' )

řídicí panel. log ( 'Tři' )

V tomto kódu jsou tři příkazy console.log, z nichž každý něco vypisuje. Nejprve se první příkaz, který vytiskne „Jedna“ v konzole, odešle do zásobníku hovorů na 1 ms (odhad) a poté se zaloguje do terminálu. Poté je druhý příkaz vložen do zásobníku volání a nyní je čas 2 ms s jedním přidaným z předchozího a poté se do konzole zaznamená „Dva“. Nakonec je poslední příkaz vložen do zásobníku volání, nyní je čas 3 ms a do konzole se zaznamená „Tři“.

Výše uvedený kód lze spustit vyvoláním následujícího příkazu:

aplikace uzlu. js

Výstup

Funkce je podrobně vysvětlena výše a při jejím zohlednění je výstup během mrknutí oka přihlášen do konzole:

Asynchronní provádění kódu v Javascriptu

Nyní refaktorujeme stejný kód zavedením zpětných volání a tím, že kód bude asynchronní. Výše uvedený kód lze refaktorovat jako:

// application.js
funkce printOne ( zpětné volání ) {
setTimeout ( funkce ( ) {
řídicí panel. log ( 'Jeden' ) ;
zpětné volání ( ) ;
} , 1000 ) ;
}
funkce printTwo ( zpětné volání ) {
setTimeout ( funkce ( ) {
řídicí panel. log ( 'Dva' ) ;
zpětné volání ( ) ;
} , 2000 ) ;
}
funkce tiskTři ( ) {
setTimeout ( funkce ( ) {
řídicí panel. log ( 'Tři' ) ;
} , 3000 ) ;
}
řídicí panel. log ( 'Začátek programu' ) ;
printOne ( funkce ( ) {
tisk Dva ( funkce ( ) {
tiskTři ( ) ;
} ) ;
} ) ;
řídicí panel. log ( 'Konec programu' ) ;

V tomto kódu výše:

  • Tři funkce jsou deklarovány pro tisk „Jedna“, „Dva“ a „Tři“, každá funkce má parametr zpětného volání, který umožňuje sekvenční provádění kódu.
  • Časový limit se nastavuje pomocí funkce setTimeout a existuje příkaz console.log pro tisk po určité prodlevě.
  • Jsou vytištěny dvě zprávy „Začátek programu“ a „Konec programu“, které označují začátek a konec programu.
  • Program se spustí vytištěním „Start programu“, po kterém se s 1sekundovým zpožděním provede funkce printOne, poté se s 2sekundovým zpožděním provede funkce printTwo a nakonec se s 3sekundovým zpožděním provede funkce printThree. zpoždění.
  • Program nečeká na asynchronní spuštění kódu uvnitř funkcí setTimeouts, které zaprotokolují příkaz „Konec programu“ před tiskem Jedničky, Dvojky a Trojky.

Výstup

Spusťte výše uvedený kód provedením tohoto příkazu v terminálu:

aplikace uzlu. js

Nyní by se výstup v terminálu ukázal asynchronně jako:

Nyní, když dokonale rozumíme synchronnímu a asynchronnímu provádění, pojďme se vrhnout na upevnění našeho konceptu smyčky událostí v Node.js.

Node.js: Mechanismus smyčky událostí

Provádění synchronních i asynchronních úloh je řízeno smyčkou událostí v Node.js. Provádění je vyvoláno, jakmile je spuštěn projekt Node.js a plynule přenáší složité úlohy do systému. Tím je zajištěno, že ostatní úlohy mohou v hlavním vláknu běžet hladce.

Vizuální vysvětlení smyčky událostí v Node.js

Smyčka událostí je v Node.js spojitá a polonekonečná. Smyčka událostí je vyvolána spuštěním skriptu kódu Node.js a je zodpovědná za provádění asynchronních volání API a volání procesů.Tick() a plánování časovačů pak obnoví provádění smyčky událostí.

V Node.js zpracovává zpětná volání pět hlavních typů front:

  • „Fronta časovače“ běžně známá jako min-hromada je zodpovědná za zpracování zpětných volání spojených s „setTimeout“ a „setInterval“.
  • Zpětná volání pro asynchronní operace jako v modulech „fs“ a „http“ jsou zpracovávána „I/O Queue“.
  • „Check Queue“ obsahuje zpětná volání pro funkci „setImmediate“, která je jedinečná pro Node.
  • „Zavřít frontu“ spravuje zpětná volání spojená s událostí uzavření jakékoli asynchronní úlohy.
  • A konečně, ve frontě „Micro Task“ jsou dvě různé fronty:
    • Fronta „nextTick“ obsahuje zpětná volání spojená s funkcí „process.nextTick“.
    • Fronta „Promise“ řídí zpětná volání související s nativním Promise.

Funkce Event Loop v Node.js

Smyčka událostí funguje podle specifických požadavků, které řídí příkaz k provedení zpětného volání. Synchronní kód Javascript uživatele má prioritu na začátku procesu, takže smyčka událostí se spustí až po vymazání zásobníku volání. Následující sekvence provádění se řídí strukturovaným vzorem:

Nejvyšší prioritu mají zpětná volání ve frontě mikroúkolů, poté se přesunou k provedení úkolů ve frontě nextTick a následují úkoly ve frontě Promise. Poté se zpracují procesy ve zpětných voláních fronty časovače, načež se fronta mikroúloh znovu navštíví po každém zpětném volání časovače. Zpětná volání ve frontách I/O, kontrolních a zavíracích frontách se pak provádějí podobným způsobem jako fronta mikroúloh navštívená po každé fázi.

Smyčka pokračuje v provádění, pokud existuje více zpětných volání ke zpracování. Když skript kódu skončí nebo nezbudou žádná zpětná volání ke zpracování, smyčka událostí se efektivně ukončí.

Nyní, když hluboce rozumíme smyčce událostí, pojďme se podívat na její funkce.

Vlastnosti smyčky událostí v Node.js

Hlavní rysy jsou:

  • Smyčka událostí je nekonečná smyčka a pokračuje v provádění úkolů, jakmile je obdrží, a přejde do režimu spánku v případě, že neexistují žádné úkoly, ale začne fungovat, jakmile je úkol přijat.
  • Úlohy ve frontě událostí se provádějí pouze tehdy, když je zásobník prázdný, což znamená, že neprobíhá žádná aktivní operace.
  • Zpětná volání a přísliby lze použít ve smyčce událostí.
  • Jelikož se smyčka událostí řídí principem fronty abstraktního datového typu, splní první úlohu a poté přejde k další.

Po důkladném pochopení smyčky událostí a logiky asynchronního a synchronního provádění může pochopení různých fází upevnit koncepty smyčky událostí.

Node.js Smyčka událostí Fáze

Jak bylo uvedeno výše, smyčka událostí je polonekonečná. Má mnoho fází, ale některé fáze se používají pro vnitřní manipulaci. Tyto fáze nemají žádný vliv na skript kódu.

Smyčka událostí sleduje funkcionalitu Queue a provádí úlohu na principu první dovnitř a první ven. Naplánované časovače bude zpracovávat operační systém, dokud nevyprší jejich platnost. Časovače, jejichž platnost vypršela, jsou poté přidány do fronty zpětných volání pro časovače.

Smyčka událostí provádí úkoly ve frontě časovače jeden po druhém, dokud nezůstanou žádné další úkoly nebo dokud nedosáhne maximálního povoleného počtu úkolů. V následujících částech jsou vysvětleny základní fáze smyček událostí.

Fáze časovačů

V Node.js je API časovače, které může naplánovat funkce, které se mají v budoucnu provést. Po uplynutí přiděleného času se provede zpětné volání časovače, jakmile je lze naplánovat; ke zpoždění však může dojít buď z konce operačního systému, nebo z důvodu provádění jiných zpětných volání.

API časovače má tři hlavní funkce:

  • setTimeout
  • setImmediate
  • nastavitInterval

Výše uvedené funkce jsou synchronní. Fáze časovače ve smyčce událostí má rozsah omezený na funkce setTimeout a setInterval. Zatímco funkce kontroly zpracovává funkci setImmediate.

Podívejme se na jednoduchý příklad pro zpevnění teoretické části:

// application.js

funkce zpožděnáFunction ( ) {

řídicí panel. log ( 'zpožděná funkce se provede po vypršení časového limitu' ) ;

}

řídicí panel. log ( 'Začátek programu' ) ;

setTimeout ( zpožděná funkce, 2000 ) ;

řídicí panel. log ( 'Konec programu' ) ;

V tomto kódu:

  • Program se spustí přihlášením příkazu „Start programu“ do terminálu.
  • Poté se zavolá delayedFunction s časovačem 2 ms, kódový skript se nezastaví a pokračuje v dalším zpracování zpoždění na pozadí.
  • Výpis „Konec programu je zaznamenán po prvním příkazu.
  • Po prodlevě 2 ms je výpis v delayedFunction zaprotokolován do terminálu.

Výstup

Výstup se zobrazí jako:

Je vidět, že kód není zastaven pro zpracování delayedFunction; posune se vpřed a po prodlevě se zpracuje zpětné volání funkce.

Čekající zpětná volání

Smyčka událostí kontroluje události, ke kterým dochází ve fázi dotazování, jako je čtení souborů, síťové aktivity nebo vstupní/výstupní úlohy. Je důležité vědět, že v Node.js jsou v této fázi dotazování zpracovávány pouze některé události. V následné iteraci smyčky událostí však mohou být určité události odloženy do nevyřízené fáze. Toto je klíčový koncept, který je třeba mít na paměti při optimalizaci a odstraňování problémů s kódem Node.js, který zahrnuje složité operace řízené událostmi.

Je důležité pochopit, že během fáze čekajících zpětných volání smyčka událostí přidává odložené události do fronty čekajících zpětných volání a provádí je. Tato fáze také zpracovává některé chyby soketu TCP, které systém vygeneroval, například chybové události ECONNREFUSED v určitých operačních systémech.

Níže je uveden příklad pro upevnění konceptu:

// application.js
konst fs = vyžadovat ( 'fs' ) ;
funkce readFileAsync ( filePath, zpětné volání ) {
fs. readFile ( './PromiseText.txt' , 'utf8' , funkce ( chyba, data ) {
-li ( chybovat ) {
řídicí panel. chyba ( ' Chyba čtení souboru : $ { chybovat. zpráva } ' ) ;
} jiný {
řídicí panel. log ( ' Soubor obsah : $ { data } ' ) ;
}
zpětné volání ( ) ;
} ) ;
}
řídicí panel. log ( 'Začátek programu' ) ;
readFileAsync ( './PromiseText.txt' , funkce ( ) {
řídicí panel. log ( 'Provedeno zpětné volání čtení souboru' ) ;
} ) ;
řídicí panel. log ( 'Konec programu' ) ;

V tomto kódu:

  • Program se spouští zalogováním příkazu „Start programu“ do terminálu.
  • ReadFileAsync je definován asynchronně pro čtení obsahu souboru „PromiseText.txt“. Je to parametrizovaná funkce, která po přečtení souboru provede funkci zpětného volání.
  • Funkce readFileAsync je volána k zahájení procesu čtení souboru.
  • V procesu čtení souboru se program nezastaví; místo toho přejde na další příkaz a přihlásí jej do terminálu „Konec programu“.
  • Asynchronní událost čtení souboru je zpracovávána na pozadí smyčkou událostí.
  • Po asynchronním načtení souboru a přihlášení obsahu do terminálu program zaznamená obsah souboru do terminálu. Poté zaprotokoluje následující zprávu „File read callback completed“.
  • Smyčka událostí zpracovává čekající operace zpětného volání v další fázi.

Výstup

Výsledkem výše uvedeného provedení je:

Nečinný, přípravná fáze v Node.js

Nečinná fáze se používá k řešení interních funkcí v Node.js, takže nejde o standardní fázi. Nemá vliv na skript kódu. Nečinná fáze je jako přestávka pro smyčku událostí, během níž se na pozadí spravuje úkoly s nízkou prioritou. Jednoduchý příklad pro pochopení této fáze je:

konst { líný } = vyžadovat ( 'idle-gc' ) ;

líný. ignorovat ( ) ;

V tomto kódu je použit modul „idle-gc“, který umožňuje ignorovat fázi nečinnosti. To slouží k řešení situací, kdy je smyčka událostí zaneprázdněna a úlohy na pozadí nejsou prováděny. Použití idle.ignore se nepovažuje za optimální, protože může způsobit problémy s výkonem.

Fáze dotazování v Node.js

Fáze průzkumu v Node.js slouží jako:

  • Zpracovává události ve frontě dotazování a provádí jejich odpovídající úkoly.
  • Rozhoduje, kolik času strávíte čekáním a kontrolou I/O operací v procesu.

Když smyčka událostí vstoupí do fáze dotazování kvůli absenci časovače, bude proveden jeden z níže uvedených úkolů:

  • Ve fázi dotazování smyčky událostí v Node.js jsou čekající I/O události zařazeny do fronty a poté provedeny v sekvenční proceduře podle principu First In a First Out, dokud se fronta nevyprázdní. Během provádění zpětných volání jsou v akci také fronty nextTick a mikroúkolů. To zajišťuje plynulost a umožňuje efektivnější a spolehlivější zpracování I/O operací.
  • Pokud je fronta prázdná a skript nebyl naplánován funkcí setImmediate(), smyčka událostí se ukončí a postoupí do další fáze (kontrola). Na druhou stranu, pokud bylo plánování skriptu provedeno funkcí setImmediate(), smyčka událostí umožňuje přidat zpětná volání do fronty, která bude provedena.

Nejlépe to ilustruje jednoduchý příklad kódu:

setTimeout ( ( ) => {

řídicí panel. log ( 'Asynchronní operace dokončena' ) ;

} , 2000 ) ;

řídicí panel. log ( 'Start' ) ;

setImmediate ( ( ) => {

řídicí panel. log ( 'setImmediate callback provedeno' ) ;

} ) ;

řídicí panel. log ( 'Konec' ) ;

V tomto kódu:

  • Dvě zprávy „Start“ a „End“ označují zahájení a ukončení programu.
  • Funkce setTimeout() nastaví funkci zpětného volání se zpožděním 2 ms a zaznamená do terminálu „Asynchronní operace dokončena“.
  • Funkce setImmediate() zaznamená do terminálu zprávu „setImmediate callback spuštěna“ poté, co byla do terminálu zaznamenána zpráva Start.

Výstup

Výstup by ukázal zprávy s pouhým minutovým pozorováním, že „Asynchronní operace dokončena“ nějakou dobu trvá a je vytištěna po zprávě „Konec“:

Kontrolní fáze Node.js

Po provedení fáze dotazování se provedou zpětná volání ve fázi kontroly. Pokud je kódový skript naplánován pomocí funkce setImmediate() a funkce dotazování je volná, smyčka událostí funguje tak, že se přesune přímo do fáze kontroly, místo aby zůstala nečinná. Funkce setImmediate() je jedinečný časovač, který funguje během různých fází smyčky událostí.

Rozhraní libuv API se používá k plánování provádění zpětného volání po dokončení fáze dotazování. Během provádění kódu smyčka událostí vstoupí do fáze dotazování, ve které čeká na příchozí požadavky na připojení. V jiném případě, pokud je zpětné volání naplánováno pomocí funkce setImmediate() a fáze dotazování je ukončena bez jakékoli aktivity, přesune se místo čekání do fáze kontroly. Pro pochopení zvažte následující příklad:

// application.js

řídicí panel. log ( 'Start' ) ;

setImmediate ( ( ) => {

řídicí panel. log ( 'Okamžité zpětné volání' ) ;

} ) ;

řídicí panel. log ( 'Konec' ) ;

V tomto kódu jsou do terminálu přihlášeny tři zprávy. Funkce setImmediate() pak nakonec odešle zpětné volání pro přihlášení zprávy “ Okamžité zpětné volání “ do terminálu.

Výstup

Výstup výše uvedeného kódu se zobrazí v následujícím pořadí:

Node.js uzavře zpětná volání

Node.js používá tuto fázi uzavření ke spuštění zpětných volání k uzavření událostí a ukončení iterace smyčky událostí. Po uzavření spojení smyčka událostí zpracovává události uzavření v této fázi. V této fázi smyčky událostí jsou „nextTick()“ a mikroúlohy generovány a zpracovávány podobně jako v jiných fázích.

Funkce process.exit se používá k ukončení smyčky událostí v každém okamžiku. Smyčka událostí bude ignorovat všechny nevyřízené asynchronní operace a proces Node.js bude ukončen.

Jednoduchý příklad ke zvážení je:

// application.js
konst síť = vyžadovat ( 'síť' ) ;
konst server = síť. createServer ( ( zásuvka ) => {
zásuvka. na ( 'zavřít' , ( ) => {
řídicí panel. log ( 'Zásuvka uzavřena' ) ;
} ) ;
zásuvka. na ( 'data' , ( data ) => {
řídicí panel. log ( 'Přijatá data:' , údaje. toString ( ) ) ;
} ) ;
} ) ;
server. na ( 'zavřít' , ( ) => {
řídicí panel. log ( 'Server uzavřen' ) ;
} ) ;
konst přístav = 3000 ;
server. poslouchat ( přístav, ( ) => {
řídicí panel. log ( `Server naslouchá na portu $ { přístav } ' ) ;
} ) ;
setTimeout ( ( ) => {
řídicí panel. log ( 'Zavírání serveru po 10 sekundách' ) ;
server. zavřít ( ) ;
proces. výstup ( ) ;
} , 10 000 ) ;

V tomto kódu:

  • const net = vyžadovat(‘net’) 'importuje síťový modul potřebný ke zpracování TCP serveru a ' const server = net.createServer((socket) => { ” vytvoří novou instanci TCP serveru.
  • socket.on(‘zavřít’, () => {… } “ poslouchá „zavřít“ na všech zásuvkách. Když je soketové spojení uzavřeno, do terminálu se zaprotokoluje zpráva „Socket Closed“.
  • socket.on(‘data’, (data) => {} ” zkontroluje příchozí data ze všech jednotlivých soketů a vytiskne je pomocí funkce “.toString()”.
  • server.on(‘zavřít’, () => {…} ” zkontroluje událost „close“ na samotném serveru, a když je připojení k serveru uzavřeno, zaznamená do terminálu zprávu „Server Closed“.
  • server.listen(port, () => {…} ” naslouchá příchozím připojením na portu.
  • setTimeout(() => {…} ” nastaví časovač na 10 ms pro uzavření serveru.

Tím končí diskuse o různých fázích smyčky událostí v Node.js. Než přejdeme k závěru, pojďme si probrat jednu poslední věc, a to jak opustit smyčku událostí v Node.js.

Ukončení smyčky událostí v Node.js

Smyčka událostí je ve fázi provádění, dokud jsou ve všech frontách fází smyčky událostí nějaké úkoly. Smyčka událostí skončí po vydání výstupní fáze a vrátí se zpětné volání výstupního posluchače, pokud ve frontách nejsou žádné další úlohy.

Explicitní způsob, jak ukončit smyčku událostí, je použít metodu „.exit“. Aktivní procesy v Node.js se okamžitě ukončí, jakmile je zavolána funkce process.exit. Všechny naplánované a čekající události budou zrušeny:

proces. na ( 'výstup' , ( kód ) => {

řídicí panel. log ( 'Ukončení s výstupním kódem.' : $ { kód } ' ) ;

} ) ;

proces. výstup ( 1 ) ;

Uživatelé mohou poslouchat funkci .exit. Je třeba poznamenat, že funkce „.exit“ musí být synchronní, protože program Node.js se ukončí, jakmile naslouchá této události.

Tím končí diskuse o smyčce událostí. Podrobný článek, který pokryl všechny koncepty, fáze a příklady související se smyčkou událostí.

Závěr

Před pochopením smyčky událostí může přehled synchronních a asynchronních konceptů pomoci pochopit tok kódu ve smyčce událostí. Synchronní provádění znamená provádění krok za krokem, zatímco asynchronní provádění znamená zastavení některých kroků bez čekání na jejich dokončení. Fungování smyčky událostí spolu se všemi fázemi spolu s vhodnými příklady je diskutováno v článku.