Како Петља догађаја функционише у ЈаваСцрипт-у?

Иако може захтевати дубинско разумевање језика као што су Ц++ и Ц за писање пуног производног кода, ЈаваСцрипт се често може написати само са основним разумевањем шта се може урадити са језиком.

Концепти, попут прослеђивања повратних позива функцијама или писања асинхроног кода, често нису тако тешки за имплементацију, због чега већина ЈаваСцрипт програмера мање брине о томе шта се дешава испод хаубе. Њима једноставно није стало до разумевања сложености које је језик дубоко апстраховао од њих.

Као ЈаваСцрипт програмеру, постаје све важније да разумемо шта се заиста дешава испод хаубе и како већина ових сложености апстрахованих од нас заиста функционише. Помаже нам да доносимо боље информисане одлуке, што заузврат може драстично повећати перформансе нашег кода.

Овај чланак се фокусира на један од веома важних, али ретко разумљивих концепата или термина у ЈаваСцрипт-у. ПЕТЉА ДОГАЂАЈА!.

Писање асинхроног кода се не може избећи у ЈаваСцрипт-у, али зашто то заиста значи код који се покреће асинхроно? тј. Петља догађаја

Пре него што схватимо како функционише петља догађаја, прво морамо да разумемо шта је сам ЈаваСцрипт и како функционише!

Шта је ЈаваСцрипт?

Пре него што наставимо, желео бих да се вратимо на саме основе. Шта је заправо ЈаваСцрипт? ЈаваСцрипт бисмо могли дефинисати као;

ЈаваСцрипт је висок ниво, интерпретиран, једнонитни неблокирајући, асинхрони, конкурентни језик.

Чекај, шта је ово? Књижна дефиниција? 🤔

Хајде да га разбијемо!

Кључне речи овде у вези са овим чланком су једнонитне, неблокирајуће, истовремене и асинхроне.

Сингле тхреад

Нит извршења је најмања секвенца програмираних инструкција којом распоређивач може управљати независно. Програмски језик је једнонитни значи да може извршити само један задатак или операцију у једном тренутку. То значи да би извршио цео процес од почетка до краја без прекида или заустављања нити.

За разлику од језика са више нити где се више процеса може покренути на неколико нити истовремено без међусобног блокирања.

Како ЈаваСцрипт може бити једнонитни и неблокирајући у исто време?

Али шта значи блокирање?

Неблокирајуће

Не постоји јединствена дефиниција блокирања; то једноставно значи ствари које се споро одвијају на нити. Дакле, неблокирање значи ствари које нису споре на нити.

  Како уклонити подвучене хипервезе у ПоверПоинту

Али чекајте, јесам ли рекао да се ЈаваСцрипт ради на једној нити? Такође сам рекао да не блокира, што значи да се задатак брзо извршава на стеку позива? Али како??? Шта кажете на то када покренемо тајмере? Лоопс?

Опустити! Сазнаћемо за мало 😉.

Истовремено

Конкуренција значи да се код истовремено извршава од стране више од једне нити.

У реду, ствари постају стварно чудан сада, како ЈаваСцрипт може бити једнонитни и истовремено истовремено? тј. извршавање свог кода са више од једне нити?

Асинхрони

Асинхроно програмирање значи да се код покреће у петљи догађаја. Када постоји операција блокирања, догађај се покреће. Код за блокирање наставља да ради без блокирања главне извршне нити. Када блокирајући код заврши са радом, он је резултат операција блокирања у реду и враћа их назад у стек.

Али ЈаваСцрипт има једну нит? Шта онда извршава овај код за блокирање док дозвољава извршавање других кодова у нити?

Пре него што наставимо, хајде да резимирамо горе наведено.

  • ЈаваСцрипт је једнонит
  • ЈаваСцрипт није блокирајући, односно спори процеси не блокирају његово извршавање
  • ЈаваСцрипт је истовремен, тј. извршава свој код у више нити у исто време
  • ЈаваСцрипт је асинхрони, тј. покреће блокирајући код негде другде.

Али горенаведено се баш не уклапа, како језик са једним нити може бити неблокирајући, истовремени и асинхрони?

Идемо мало дубље, спустимо се на ЈаваСцрипт рунтиме машине, В8, можда има неке скривене нити којих нисмо свесни.

В8 мотор

Мотор В8 је мотор високих перформанси отвореног кода за извршавање веб склопова за ЈаваСцрипт написан у Ц++ од стране Гоогле-а. Већина претраживача покреће ЈаваСцрипт користећи В8 мотор, а чак га и популарно окружење за ноде јс користи.

На једноставном енглеском, В8 је Ц++ програм, који прима ЈаваСцрипт код, компајлира га и извршава.

В8 ради две главне ствари;

  • Додела меморије у хрпи
  • Контекст извршавања стека позива

Нажалост, наша сумња је била погрешна. В8 има само један стек позива, замислите стек позива као нит.

Једна нит === један стек позива === једно по једно извршавање.

Слика – Хакерско подне

Пошто В8 има само један стек позива, како онда ЈаваСцрипт ради истовремено и асинхроно без блокирања главне извршне нити?

  Поуздана платформа за мала и велика предузећа

Хајде да покушамо да сазнамо писањем једноставног, али уобичајеног асинхроног кода и анализирамо га заједно.

ЈаваСцрипт покреће сваки код ред по ред, један за другим (једнонитни). Као што се и очекивало, први ред се овде штампа у конзоли, али зашто се последњи ред штампа пре истека кода? Зашто процес извршавања не сачека код истека (блокирање) пре него што настави да покрене последњи ред?

Изгледа да нам је нека друга нит помогла да извршимо то временско ограничење пошто смо прилично сигурни да нит може да изврши само један задатак у било ком тренутку.

Хајде да кратко завиримо у В8 изворни код за неко време.

Чекај шта??!!! У В8 нема функција тајмера, нема ДОМ-а? Нема догађаја? Нема АЈАКС-а?…. Иееееесссс!!!

Догађаји, ДОМ, тајмери ​​итд. нису део основне имплементације ЈаваСцрипт-а, ЈаваСцрипт је стриктно усклађен са спецификацијама Ецма скрипти и различите његове верзије се често помињу у складу са његовим спецификацијама Ецма скрипти (ЕС Кс).

Ток рада извршења

Догађаји, тајмери, Ајак захтеви се обезбеђују на страни клијента од стране претраживача и често се називају Веб АПИ. Они су ти који омогућавају да једнонитни ЈаваСцрипт буде неблокирајући, истовремени и асинхрони! Али како?

Постоје три главна одељка за радни ток извршавања било ког ЈаваСцрипт програма, стек позива, веб АПИ и ред задатака.

Стацк позива

Стек је структура података у којој је последњи додат елемент увек први који се уклања из стека, можете га замислити као стог плоче у којој се прва може уклонити само прва плоча која је последња додата. Стацк позива није ништа друго до структура података стека у којој се задаци или код извршавају у складу са тим.

Хајде да размотримо следећи пример;

Извор – хттпс://иоуту.бе/8аГхЗКкоФбК

Када позовете функцију принтСкуаре() , она се гура у стек позива, функција принтСкуаре() позива функцију скуаре(). Функција скуаре() се гура у стек и такође позива функцију мултипли(). Функција множења је гурнута на стек. Пошто се функција множења враћа и последња је ствар која је гурнута у стек, прво се решава и уклања из стека, а затим следи функција скуаре(), а затим функција принтСкуаре().

Веб АПИ

Овде се извршава код којим не рукује В8 мотор да не би „блокирао“ главну извршну нит. Када стек позива наиђе на функцију веб АПИ-ја, процес се одмах предаје веб АПИ-ју, где се извршава и ослобађа стек позива да обавља друге операције током његовог извршавања.

  7 најбољих мобилних ММО игара које можете играти данас

Вратимо се на наш сетТимеоут пример изнад;

Када покренемо код, прва линија цонсоле.лог бива гурнута у стек и добијамо наш излаз скоро одмах, када дођемо до временског ограничења, тајмерима управља претраживач и нису део основне имплементације В8, већ се гура уместо тога на веб АПИ, ослобађајући стек како би могао да обавља друге операције.

Док временско ограничење још увек траје, стек прелази на следећу линију радње и покреће последњи цонсоле.лог, што објашњава зашто то добијамо пре излаза тајмера. Када се тајмер заврши, нешто се дешава. Тајмер цонсоле.лог ин затим магично се појављује у групи позива!

Како?

Петља догађаја

Пре него што разговарамо о петљи догађаја, хајде да прво прођемо кроз функцију реда задатака.

Да се ​​вратимо на наш пример временског ограничења, када веб АПИ заврши са извршавањем задатка, он га не враћа само назад у стек позива аутоматски. Иде у ред задатака.

Ред је структура података која функционише на принципу Први у први, тако да када се задаци гурају у ред, они излазе истим редоследом. Задаци које су извршили веб АПИ-ји, који се гурају у ред задатака, а затим се враћају у стек позива да би се њихов резултат одштампао.

Али чекај. КОЈА ЈЕ ПЕТЉА ДОГАЂАЈА???

Извор – хттпс://иоуту.бе/8аГхЗКкоФбК

Петља догађаја је процес који чека да се стек позива очисти пре него што гура повратне позиве из реда задатака у стек позива. Када се стек очисти, петља догађаја се покреће и проверава ред задатака за доступне повратне позиве. Ако их има, гура га у стек позива, чека да се стек позива поново очисти и понавља исти процес.

Извор – хттпс://ввв.куора.цом/Хов-доес-ан-евент-лооп-ворк/ансвер/Тимотхи-Маквелл

Горњи дијаграм показује основни ток рада између петље догађаја и реда задатака.

Закључак

Иако је ово врло основни увод, концепт асинхроног програмирања у ЈаваСцрипт-у даје довољно увида да се јасно разуме шта се дешава испод хаубе и како ЈаваСцрипт може да ради истовремено и асинхроно са само једном нити.

ЈаваСцрипт је увек на захтев, а ако сте радознали да научите, саветовао бих вам да ово проверите Удеми цоурсе.