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

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

Шта је ЈаваСцрипт петља догађаја?

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

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

Да бисте разумели потребу за ЈаваСцрипт петљом догађаја и асинхроним програмирањем. Морате разумети који проблем у суштини решава.

Узмите овај код, на пример:

functionlongRunningFunction() {
// This function does something that takes a long time to execute.
for (var i = 0; i < 100000; i++) {
console.log("Hello")
}
}

functionshortRunningFunction(a) {
return a * 2 ;
}

functionmain() {
var startTime = Date.now();
longRunningFunction();

var endTime = Date.now();

// Prints the amount of time it took to execute functions
console.log(shortRunningFunction(2));
console.log("Time taken: " + (endTime - startTime) + " milliseconds");
}

main();

Овај код прво дефинише функцију тзв лонгРуннингФунцтион(). Ова функција ће обавити неку врсту сложеног задатка који одузима много времена. У овом случају, врши а за петља која се понавља преко 100.000 пута. То значи да цонсоле.лог("Здраво") ради 100.000 пута.

У зависности од брзине рачунара, ово може потрајати и блокирати схортРуннингФунцтион() од непосредног извршења до завршетка претходне функције.

За контекст, ево поређења времена потребног за покретање обе функције:

А онда сингл схортРуннингФунцтион():

Разлика између операције од 2.351 милисекунде и операције од 0 милисекунди је очигледна када имате за циљ да направите ефикасну апликацију.

Како петља догађаја помаже у перформансама апликације

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

Стацк позива

ЈаваСцрипт стек позива је од суштинског значаја за то како ЈаваСцрипт управља позивима функција и догађаја из ваше апликације. ЈаваСцрипт код се компилира од врха до дна. Међутим, Ноде.јс, након читања кода, Ноде.јс ће доделити позиве функцијама од дна ка врху. Док чита, гура дефинисане функције као оквире у стек позива једну по једну.

Стек позива је одговоран за одржавање контекста извршавања и исправног редоследа функција. То ради тако што ради као стек Ласт-Ин-Фирст-Оут (ЛИФО).

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

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

Либув веб АПИ

У сржи ЈаваСцрипт-ових асинхроних програма је либув. Либув библиотека је написана у програмском језику Ц, који може да комуницира са оперативним системом АПИ-ји ниског нивоа. Библиотека ће обезбедити неколико АПИ-ја који омогућавају да се ЈаваСцрипт код ради паралелно са другим код. АПИ-ји за креирање нити, АПИ за комуникацију између нити и АПИ за управљање синхронизацијом нити.

На пример, када користите сетТимеоут у Ноде.јс да паузирате извршење. Тајмер је подешен преко либув-а, који управља петљом догађаја да изврши функцију повратног позива када прође наведено кашњење.

Слично томе, када обављате мрежне операције асинхроно, либув управља тим операцијама у неблокирајућем на начин, обезбеђујући да други задаци могу да наставе са обрадом без чекања да се улазно/излазна (И/О) операција крај.

Ред за повратни позив и догађај

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

Ево како иде редослед:

  1. ЈаваСцрипт премешта асинхроне задатке у либув да би он могао да обрађује, и наставља да одмах обрађује следећи задатак.
  2. Када се асинхрони задатак заврши, ЈаваСцрипт додаје своју функцију повратног позива у ред за повратни позив.
  3. ЈаваСцрипт наставља да извршава друге задатке у стеку позива све док не заврши са свим тренутним редоследом.
  4. Када је стек позива празан, ЈаваСцрипт гледа у ред повратних позива.
  5. Ако постоји повратни позив у реду, он гура први у стек позива и извршава га.

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

Циклус петље догађаја

Петља догађаја такође има нешто што се зове ред микро задатака. Овај специјални ред у петљи догађаја садржи микрозадатке који су планирани да се изврше чим се заврши тренутни задатак у стеку позива. Ово извршење се дешава пре следећег рендеровања или итерације петље догађаја. Микрозадаци су задаци високог приоритета са приоритетом над редовним задацима у петљи догађаја.

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

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

Без микрозадатака, петља догађаја за овај задатак би функционисала на следећи начин:

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

Међутим, са микрозадацима, петља догађаја функционише другачије:

  1. Корисник више пута кликне на дугме и покреће операцију асинхроног преузимања података.
  2. Како се операције преузимања података довршавају, петља догађаја додаје њихове одговарајуће повратне позиве у ред микрозадатака.
  3. Петља догађаја почиње да обрађује задатке у реду микро задатака одмах након завршетка тренутног задатка (клик на дугме).
  4. Ажурирање корисничког интерфејса на основу резултата преузимања података се извршава пре следећег редовног задатка, пружајући боље корисничко искуство.

Ево примера кода:

const fetchData = () => {
returnnewPromise(resolve => {
setTimeout(() => resolve('Data from fetch'), 2000);
});
};

document.getElementById('fetch-button').addEventListener('click', () => {
fetchData().then(data => {
// This UI update will run before the next rendering cycle
updateUI(data);
});
});

У овом примеру, сваки клик на дугме „Преузми“ позива фетцхДата(). Свака операција преузимања података планира се као микрозадатак. На основу преузетих података, ажурирање корисничког интерфејса се извршава одмах након завршетка сваке операције преузимања, пре било ког другог рендеровања или петље догађаја.

Ово осигурава да корисници виде ажуриране податке без икаквих кашњења због других задатака у петљи догађаја.

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

Импликације петље догађаја за развој веба

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

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