Funksiyalarni optimallashtirish: Debounce va Throttle farqlari, lift va kran analogiyasi, universal implementatsiyalar hamda scroll, resize, input hodisalarida qo'llash.
Chapter 30.4'da debounce'ga qisqacha kirish qilgan edik. Bu bobda debounce va uning "aka-ukasi" throttle'ni chuqur, umumiy (universal) function shaklida o'rganamiz.
Ba'zi hodisalar (Chapter 33) — masalan, scroll, resize, input — juda tez-tez, ba'zan soniyasiga o'nlab marta ishga tushadi. Agar bu hodisaga bog'langan function "og'ir" (masalan, server so'rovi yuboradigan) bo'lsa, bu dasturni sekinlashtirishi yoki hatto serverga haddan tashqari ko'p so'rov yuborishi mumkin.
🚪 Debounce — bu lift eshigi: eshik yopilishidan oldin, agar kimdir yana tugmani bossa, taymer qaytadan boshlanadi — eshik faqat odamlar "tinchigandan" keyin yopiladi.
🚰 Throttle — bu suv kranidan chiqadigan tomchilar: qancha zo'r bersangiz ham, suv faqat belgilangan tezlikda (masalan, har soniyada bir marta) chiqadi, ko'proq emas.
Debounce — function faqat, oxirgi chaqiruvdan keyin belgilangan vaqt o'tib, hech qanday yangi chaqiruv bo'lmasagina ishga tushadi.
script.jsJavaScriptfunction debounce(func, delay) {let timeoutId;return function (...args) {clearTimeout(timeoutId);timeoutId = setTimeout(() => {func.apply(this, args);}, delay);};}
debounce(func, delay) — Chapter 14'da o'rgangan Higher-Order Function: u function qabul qilib, yangi, "debounce qilingan" function qaytaradi.clearTimeout) bekor qilinadi.delay vaqt ichida yana chaqiruv bo'lmasa, asl func ishga tushadi.func.apply(this, args) — Chapter 13'da o'rgangan apply() orqali, asl this kontekstini va barcha argumentlarni (Chapter 6'dagi rest parameters — ...args) to'g'ri uzatadi.script.jsJavaScriptfunction searchAPI(query) {console.log("Qidirilmoqda: " + query);// haqiqiy loyihada bu yerda fetch() chaqirilardi (Chapter 37)}let debouncedSearch = debounce(searchAPI, 500);let input = document.getElementById("searchInput");input.addEventListener("input", function (event) {debouncedSearch(event.target.value);});
Foydalanuvchi qanchalik tez yozmasin, searchAPI faqat foydalanuvchi yozishni to'xtatgandan 500ms keyin, faqat bir marta chaqiriladi — bu keraksiz ko'p server so'rovlarining oldini oladi.
Throttle — function'ning belgilangan vaqt oralig'ida faqat bir marta ishga tushishini kafolatlaydi, hodisa qanchalik tez-tez chaqirilishidan qat'i nazar. Debounce'dan farqli, throttle — chaqiruvlarni "kutmaydi", balki ularni muntazam oraliqlarga taqsimlaydi.
| Xususiyat | Debounce | Throttle |
|---|---|---|
| Qachon ishga tushadi | Faqat chaqiruvlar to'xtagandan keyin | Muntazam oraliqlarda, chaqiruvlar davom etsa ham |
| Mos qo'llanilish | Qidiruv input, forma validatsiyasi | Scroll, resize, sichqoncha harakati |
| Natija | Bitta, "oxirgi" chaqiruv | Bir nechta, muntazam chaqiruvlar |
code.textTEXTFoydalanuvchi harakati: |--|-|--|---|-|--|--------|(juda tez-tez chaqiriladi)Debounce natijasi: | ← faqat OXIRIDA, bir marta(harakat to'xtaganda)Throttle natijasi: | | | | ← muntazam oraliqlarda(harakat davom etsa ham)
script.jsJavaScriptfunction throttle(func, limit) {let inThrottle = false;return function (...args) {if (!inThrottle) {func.apply(this, args);inThrottle = true;setTimeout(() => {inThrottle = false;}, limit);}};}
inThrottle — closure (Chapter 12) orqali "eslab qolinadigan" holat, function hozir "sovutish davrida"mi yoki yo'qmi, buni bildiradi.inThrottle — false bo'lsa (ya'ni "sovutish davri" tugagan), func darhol ishga tushadi, va inThrottle — truega o'rnatiladi.limit millisekunddan keyin, inThrottle qayta falsega qaytariladi — endi keyingi chaqiruv ishlashi mumkin.script.jsJavaScriptfunction logScrollPosition() {console.log("Scroll pozitsiyasi: " + window.scrollY);}let throttledScroll = throttle(logScrollPosition, 1000);window.addEventListener("scroll", throttledScroll);
Foydalanuvchi qanchalik tez scroll qilmasin, logScrollPosition — soniyasiga faqat bir marta ishga tushadi, bu esa unumdorlikni saqlaydi.
🔥 Important
Qoida sifatida: agar sizga faqat "harakat tugagandan keyingi yakuniy natija" kerak bo'lsa (masalan, qidiruv so'rovi) — debounce. Agar sizga harakat davomida muntazam, lekin kamdan-kam yangilanishlar kerak bo'lsa (masalan, scroll pozitsiyasini kuzatish) — throttle.
Task:
Chapter 44.2'dagi debounce functionidan foydalanib, oynani o'lchamini o'zgartirish (resize) hodisasida, foydalanuvchi o'lchamni o'zgartirishni to'xtatgandan 300ms keyin, oynaning yangi innerWidthini konsolga chiqaring.
Required Concepts:
debounceresize eventwindow.addEventListener("resize", debounce(() => console.log(window.innerWidth), 300));Task:
Chapter 44.3'dagi throttle functionidan foydalanib, sichqoncha harakati (mousemove) hodisasida, har 500msda sichqonchaning clientX, clientY koordinatalarini konsolga chiqaring.
Required Concepts:
throttlemousemove eventdocument.addEventListener("mousemove", throttle((e) => console.log(e.clientX, e.clientY), 500));Task:
debounce va throttle functionlarini birlashtirib, oddiy "tugma bosish hisoblagichi" yasang: bitta tugmaga ikkita alohida click listener qo'shing — biri debounce (500ms) bilan, ikkinchisi throttle (500ms) bilan o'ralgan bo'lsin. Tugmani tez-tez (5-6 marta ketma-ket) bosib, ikkalasining nechta marta ishga tushganini solishtiring.
Required Concepts:
debounce vs throttle amaliy farqiscript.jsJavaScriptfunction debounce(func, delay) {let timeoutId;return function (...args) {clearTimeout(timeoutId);timeoutId = setTimeout(() => func.apply(this, args), delay);};}let log = debounce(() => console.log("Ishladi"), 1000);log();log();log();
Agar bu uchta chaqiruv bir zumda (masalan, 10ms ichida) ketma-ket bajarilsa, nechta marta "Ishladi" chiqadi?
🧠 Think first! Javobni ko'rishdan oldin kamida 30 soniya o'ylang.
<details> <summary>Answer</summary> Faqat bitta marta, "Ishladi".Why?
Har bir log() chaqiruvi — avvalgi timerni clearTimeout() orqali bekor qiladi va yangisini boshlaydi. Uchala chaqiruv ham bir zumda (10ms ichida) bo'lgani uchun, faqat oxirgi timer "omon qoladi" va 1000ms dan keyin ishga tushadi.
Quyidagi kodda muammo bor:
script.jsJavaScriptfunction throttle(func, limit) {let inThrottle;return function () {if (!inThrottle) {func();inThrottle = true;}// setTimeout orqali inThrottle'ni qayta false qilish YO'Q};}let logPosition = throttle(() => console.log("Scroll"), 1000);window.addEventListener("scroll", logPosition);
Your Task:
Yechim:
</details>script.jsJavaScriptfunction throttle(func, limit) {let inThrottle;return function (...args) {if (!inThrottle) {func.apply(this, args);inThrottle = true;setTimeout(() => {inThrottle = false; // MUHIM: qayta false qilish}, limit);}};}
clearTimeout/setTimeout va closure orqali "holat"ni saqlab turadi.func.apply(this, args) — asl this va argumentlarni to'g'ri uzatish uchun muhim.script.jsJavaScriptfunction debounce(func, delay) {let timeoutId;return function (...args) {clearTimeout(timeoutId);timeoutId = setTimeout(() => func.apply(this, args), delay);};}function throttle(func, limit) {let inThrottle;return function (...args) {if (!inThrottle) {func.apply(this, args);inThrottle = true;setTimeout(() => inThrottle = false, limit);}};}
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: