JavaScript dvigatelining ichki mexanizmi: Single-Threaded tabiati, Call Stack (LIFO), Web API lar, Callback Queue va Event Loop, Microtask vs Macrotask ustuvorligi.
Bu — butun kitobdagi eng chuqur va eng muhim mavzulardan biri. Chapter 26-28'da ko'rgan barcha "sehrli" xatti-harakatlar (setTimeout nega asinxron, await nega "pauza" qiladi) — barchasi shu bobda tushuntiriladigan Event Loop mexanizmiga bog'liq.
JavaScript — bitta oqimli (single-threaded) dasturlash tili, ya'ni u bir vaqtning o'zida faqat bitta amalni bajara oladi.
👤 JavaScript'ni bitta kassir ishlaydigan do'konga o'xshating: kassir bir vaqtning o'zida faqat bitta mijozga xizmat ko'rsata oladi. Agar kassir "keyingi tovar keladigan payt"ni kutib turaversa (masalan, ombordan tovar olib kelishni), navbatdagi barcha mijozlar kutib turishga majbur bo'lardi.
Savol tug'iladi: unda setTimeout, tarmoq so'rovlari qanday "bir vaqtda" ishlaydi?
Javob — Event Loop mexanizmida, va bu mexanizm JavaScript engine'ning o'zida emas, balki uni ishga tushiruvchi muhitda (brauzer yoki Node.js) joylashgan.
Call Stack — hozirda bajarilayotgan function'larni "kuzatib boruvchi" tuzilma. U — LIFO (Last In, First Out — oxirgi kirgan birinchi chiqadi) tamoyili bilan ishlaydi.
📚 Call Stack — bu bir-birining ustiga qo'yilgan kitoblar uyumi: siz faqat eng tepadagi kitobni olishingiz (ya'ni faqat eng oxirgi chaqirilgan functionni tugatishingiz) mumkin, birinchi qo'yilgan kitobni olish uchun avval barcha tepadagilarni olib tashlashingiz kerak.
script.jsJavaScriptfunction multiply(a, b) {return a * b;}function square(n) {return multiply(n, n);}function printSquare(n) {console.log(square(n));}printSquare(5);
code.textTEXT1-qadam: 2-qadam: 3-qadam: 4-qadam (qaytish):[printSquare] → [square] → [multiply] → [square] → [printSquare] → [][printSquare] [square] [printSquare][printSquare]
Har bir function chaqirilganda, u "stack"ning tepasiga qo'shiladi. Function tugagach (natija qaytargach), u stack'dan olib tashlanadi, va boshqaruv uni chaqirgan functionga qaytadi.
🔥 Important
Agar Call Stack juda ko'p to'lib ketsa (masalan, cheksiz rekursiya tufayli), "Maximum call stack size exceeded" xatoligi yuzaga keladi — biz buni Chapter 22'da (Getter/Setter infinite loop) ko'rgan edik.
setTimeout, tarmoq so'rovlari (fetch), DOM hodisalari — bularning barchasi JavaScript engine'ining o'zida emas, balki brauzer (yoki Node.js) taqdim etadigan Web APIlarda ishlaydi. Ular tugagach, ularning callback'i Callback Queue (yoki Task Queue)ga "navbatga" qo'yiladi.
code.textTEXT┌─────────────────┐ ┌──────────────┐│ Call Stack │ │ Web APIs ││ │ │ ││ main() │───────▶│ setTimeout ││ │ │ fetch │└─────────────────┘ └──────┬───────┘│ (vaqt tugagach)▼┌──────────────────┐│ Callback Queue │└────────┬─────────┘│┌───────────▼───────────┐│ EVENT LOOP ││ (Call Stack bo'shmi?) │└───────────────────────┘
Event Loop — doimiy ravishda ikkita narsani tekshirib turuvchi mexanizm:
Agar ikkalasi ham "ha" bo'lsa, Event Loop navbatdagi vazifani Callback Queue'dan olib, Call Stack'ga qo'shadi (ya'ni uni ishga tushiradi).
script.jsJavaScriptconsole.log("1");setTimeout(function () {console.log("2");}, 0);console.log("3");
| Qadam | Call Stack | Web API | Callback Queue | Konsol |
|---|---|---|---|---|
| 1 | console.log("1") | — | — | "1" chiqadi |
| 2 | setTimeout(...) chaqiriladi | Timer boshlandi | — | — |
| 3 | console.log("3") | Timer tugadi | callback navbatga qo'yiladi | "3" chiqadi |
| 4 | bo'sh | — | callback bor | Event Loop callback'ni oladi |
| 5 | console.log("2") ishga tushadi | — | — | "2" chiqadi |
Garchi setTimeoutning kutish vaqti 0 bo'lsa ham, uning callback'i Call Stack to'liq bo'shagandan keyingina ishga tushirilishi mumkin. Shuning uchun natija har doim 1, 3, 2 bo'ladi, 1, 2, 3 emas.
💡 Key Idea
setTimeout(fn, 0) — "buni darhol bajar" degani emas, balki "buni Call Stack bo'shagach, imkon qadar tezroq bajar" degani.
Aslida navbatlar (queue) ikki xil: Microtask Queue (Promise'lar uchun) va Macrotask Queue (setTimeout, setInterval uchun). Microtask'lar har doim Macrotask'lardan oldinroq ishlov olinadi.
| Queue turi | Nimalar kiradi | Ustuvorlik |
|---|---|---|
| Microtask Queue | Promise .then/.catch/.finally, async/await | Yuqori (birinchi) |
| Macrotask Queue | setTimeout, setInterval, DOM hodisalari | Past (keyin) |
script.jsJavaScriptconsole.log("1");setTimeout(function () {console.log("2 (macrotask)");}, 0);Promise.resolve().then(function () {console.log("3 (microtask)");});console.log("4");
Natija:
code.textTEXT143 (microtask)2 (macrotask)
code.textTEXT1. Call Stack (sinxron kod) — to'liq tugaydi↓2. Barcha Microtask'lar (Promise) — navbat bo'sh bo'lguncha bajariladi↓3. Birinchi Macrotask (setTimeout va h.k.)↓(yana Microtask'lar tekshiriladi, keyin keyingi Macrotask...)
🔥 Important
Har bir Macrotask'dan oldin, Event Loop butun Microtask Queue'ni to'liq bo'shatadi. Shuning uchun Promise'lar setTimeoutdan "tezroq" (aslida — oldinroq) ishga tushadi, garchi ikkalasi ham "asinxron" bo'lsa-da.
Task:
Quyidagi kodning konsolga chiqish tartibini oldindan ayting, keyin ishga tushirib tekshiring:
script.jsJavaScriptconsole.log("Boshi");setTimeout(() => console.log("Timeout"), 100);console.log("Oxiri");
Required Concepts:
Task:
Quyidagi kodning to'liq chiqish tartibini bashorat qiling:
script.jsJavaScriptconsole.log("1");setTimeout(() => console.log("2"), 0);Promise.resolve().then(() => console.log("3"));Promise.resolve().then(() => console.log("4"));console.log("5");
Required Concepts:
Task:
Quyidagi murakkab kodning chiqish tartibini bashorat qiling va tushuntiring:
script.jsJavaScriptconsole.log("A");setTimeout(() => console.log("B"), 0);Promise.resolve().then(() => console.log("C")).then(() => console.log("D"));setTimeout(() => console.log("E"), 0);console.log("F");
Required Concepts:
script.jsJavaScriptfunction first() {console.log("first");second();console.log("first tugadi");}function second() {console.log("second");}first();
🧠 Think first! Javobni ko'rishdan oldin kamida 30 soniya o'ylang.
<details> <summary>Answer</summary> first second first tugadiWhy?
first() chaqirilganda, u Call Stack'ga qo'shiladi. "first" chiqadi. Keyin second() chaqiriladi — u ham Call Stack'ga (firstning ustiga) qo'shiladi, "second" chiqadi, va second() tugab, stack'dan olib tashlanadi. Boshqaruv first()ga qaytadi, va "first tugadi" chiqadi.
Dasturchi quyidagi kodni yozgan va natija "1, 2, 3" tartibida chiqishini kutgan, lekin "1, 3, 2" chiqmoqda:
script.jsJavaScriptconsole.log("1");setTimeout(() => {console.log("2");}, 0);console.log("3");
Your Task:
Agar chindan ham ketma-ket, sinxron tartibda ishlashi kerak bo'lsa:
script.jsJavaScriptconsole.log("1");console.log("2"); // setTimeout o'rniga to'g'ridan-to'g'riconsole.log("3");
Yoki agar "2" chindan ham kechiktirilishi kerak bo'lsa, unda "3" ham o'sha kechikishdan keyin kelishi normal holat — buni async/await bilan boshqarish mumkin:
</details>script.jsJavaScriptasync function run() {console.log("1");await new Promise(resolve => setTimeout(resolve, 0));console.log("2");console.log("3");}run();
setTimeout, fetch kabi amallarni "fonda" bajaradi.setTimeout)dan oldinroq bajariladi.setTimeout(fn, 0)) dan oldin tugaydi.Bajarilish tartibi:
.then/.catch/.finally, async/await)setTimeout, setInterval)Mavzu bo‘yicha tushunchalaringizni interaktiv test orqali sinovdan o‘tkazing va natijalarni bilib oling.
Darslikda o‘rganilgan qoidalarga asosan real kod yozing, testlardan o‘tkazing va yechimlarni mustahkamlang.
Test Sinovi
Hali topshirilmagan (kamida 75% kerak)
Amaliy Masalalar
0 / 3 ta yechildi (kamida 75% kerak)
Dars sifati va mazmunini yaxshilash uchun o‘z haqqoniy bahoingizni qoldiring.
Mavzuni to‘liq o‘zlashtirish uchun test sinovi, amaliy kodlash va bog‘liq darslar
O‘z bilimingizni interaktiv test savollari orqali tekshiring va darhol xatolarni tahlil qiling.
Nazariyani real kod yozish bilan mustahkamlang, avtomatik testlardan o‘ting va XP to‘plang.
Kurs bo‘yicha keyingi va bog‘liq mavzular: