Дарси 18 · 🏁 Лоиҳаи хурди №2 + Кори назоратии №2
Лоиҳаи хурд: барнома дар API-и оммавӣ
Лоиҳаи дуюм барои портфолио — аллакай «калонсолона»: он барои маълумот ба интернет мераванд, боркуниро нишон медиҳад, аз хатоҳои шабака мегузарад, бо ҳар ҳарф сервер-ро бо дархостҳо пур намекунад ва тавассути Vite ба ҷамъбасти тайёр ҷамъ мешавад. Маҳз ҳамин тавр виҷетҳои обуҳаво, ҷустуҷӯи маҳсулот ва лентаҳои хабарҳо сохта шудаанд. Имрӯз шумо лоиҳаро ҳимоя мекунед, коди ҳамдигарро месанҷед ва Кори назоратии №2-ро бе ЗС менависед.
Варианти барномаро дар API-и оммавӣ интихоб кардан ва онро якҷоя бо ЗС ба қадамҳо тақсим намудан
Ҳолатҳои loading / error / empty / success-ро нишон додан ва ҷавобҳои кӯҳнаро нишон надодан
Дархостҳоро тавассути debounce маҳдуд кардан ва кодро ба модулҳо тақсим намудан
Лоиҳаро тавассути Vite ҷамъ кардан (npm run build) ва ба репозиторий бор намудан
Лоиҳаро дар 5 дақиқа ҳимоя кардан ва code review-ро дар ҷуфт гузаронидан
Кори назоратии №2-ро дар 30 дақиқа навиштан: объектҳо, async/await, fetch, коркарди хатоҳо
Ростқавлона таҳлил кардан, ки ЗС дар куҷо вақтро сарфа кард ва дар куҷо аз роҳ бурд
Бо ин саҳифа чӣ тавр кор кардан лозим
Имрӯз ду блок аст. Якум — лоиҳаи хурд : вазифа, меъёрҳои баҳодиҳӣ (0–100), нақша бо ЗС, ду гармкунӣ оид ба ҳолатҳо ва дархостҳо, қолаби ибтидоӣ дар майдончаи озмоишӣ, ревью дар ҷуфтҳо ва ҳимоя. Дуюм — Кори назоратии №2 : дар қисми 11 версияи пурраи озмоишӣ бе ишораҳо ҷойгир аст. Барои гармкуниҳо мо ба шабакаи ҳақиқӣ намеравем: ба ҷои fetch «сервери сохта»-ро аз Promise ва setTimeout истифода мебарем — ҳамин тавр натиҷа ҳамеша яксон аст ва онро худкор санҷидан мумкин аст. Лоиҳаи худро шумо дар VS Code-и худ ҷамъ мекунед.
01 Вазифа: вариантро интихоб кунед
Лоиҳа аз он чизе ҷамъ мешавад, ки дар дарсҳои 13–17 гузаштед: ғайримуттаҳидӣ (async), fetch, ҳолатҳои боркунӣ, debounce, модулҳо ва ҷамъбасти Vite. Яке аз се вариантро интихоб кунед. Ҳамаи онҳо бо як меъёр баҳо дода мешаванд, API-ҳо ҳама кушода ҳастанд ва калид талаб намекунанд.
Варианти А. Ҷустуҷӯи маҳсулот
Майдони ҷустуҷӯ, дар зери он — кортаҳои маҳсулот. Дархост бо таъхир (debounce) мерасад, то боркунӣ меравад — нишондиҳанда, агар чизе наёфтанд — паёми фаҳмо.
API: dummyjson.com/products/search?q=phone&limit=10
Варианти Б. Обуҳаво дар шаҳрҳо
Рӯйхати шаҳрҳо (Душанбе, Хуҷанд, Бохтар, Кӯлоб ва шаҳрҳои худатон). Шаҳрро интихоб мекунед — ҳарорат ва шамолро мебинед. Хатои шабакаро бо тугма такрор кардан мумкин аст.
API: api.open-meteo.com/v1/forecast бо параметрҳои latitude, longitude, current=temperature_2m,wind_speed_10m
Варианти В. Одамон ва постҳои онҳо
Ҷустуҷӯи корбар аз рӯи ном, ҳангоми интихоб — постҳои ӯ. Ду дархости вобаста: аввал одам, баъд сабтҳои ӯ.
API: jsonplaceholder.typicode.com: /users ва /posts?userId=1
Мураккабӣ тақрибан баробар аст: дар маҳсулот мантиқи ҷустуҷӯ бештар аст, дар обуҳаво — таҳлили ҷавоби дарунҷойгир, дар корбарон — дархостҳои вобаста. Ғояи худро дар API-и кушодаи дигар пешниҳод кардан мумкин аст, агар он калид надошта бошад, аз браузер (CORS) кор кунад ва ҳаҷмаш ҳамон қадар бошад — инро бо муаллим пеш аз оғози кор мувофиқа кунед.
Монандӣ аз ҳаёт
Шумо дар чойхона тавассути пешхизмат палав фармоиш медиҳед. То он замон, ки мепазад — «фармоиш қабул шуд»-ро мебинед (loading). Агар палав нест — пешхизмат ростқавлона мегӯяд «тамом шуд» (empty), ва агар дар ошхона хатогӣ рух дод — «бубахшед, боз кӯшиш кунед» (error). Пешхизмати бад хомӯш аст ва умуман ҷавоб намедиҳад — ва шумо намедонед, интизор шавед ё равед. Барномаи шумо бояд мисли пешхизмати хуб рафтор кунад.
Дар охир чиро нишон медиҳед
Барномаи корӣ — бе хато дар консол кушода мешавад, ҳангоми хомӯш будани шабака хатои ботартибро нишон медиҳад.
Репозиторий дар GitHub бо коди Vite, README ва скриншот; фармони npm run build бе хато мегузарад.
Ҳимояи 5-дақиқагӣ — намоиш, шарҳи код ва ҷавоб ба саволҳо.
Таҳлили кӯтоҳи «ЗС дар лоиҳа» — қисми 12: ЗС дар куҷо кумак кард, дар куҷо аз роҳ бурд.
Қоидаҳои курс дар ин ҷо ҳам амал мекунанд
ЗС-ро истифода бурдан мумкин аст, аммо: аввал 15 дақиқа худатон кӯшиш мекунед, кодеро, ки сатр ба сатр фаҳмонида наметавонед, намегузоред, ва дар ҳимоя муаллим ҳақ дорад, ки хоҳиш кунад ҳар кадом сатрро фаҳмонед. Натавонистед — холҳои ин қисм кам карда мешаванд. Аммо дар Кори назоратии №2 ЗС комилан хомӯш аст .
02 Талабот: MVP ва бонусҳо
MVP — версияи ҳадди ақал, ки аллакай аз аввал то охир кор мекунад. Аввал онро пурра месозем, ва танҳо баъд оро медиҳем. Лоиҳа бе MVP баҳои баланд намегирад, ҳар қадар бонус дар он бошад ҳам.
MVP — барои ҳамаи вариантҳо ҳатмист
№ Талабот Чӣ тавр месанҷем 1 Маълумот аз API-и оммавӣ тавассути fetch ва async/await меояд дар ҷадвали Network дархост намоён аст, дар код маълумоти «холӣ»-и ҷойгузин нест 2 Санҷиши response.ok: ҷавоби 404 ё 500 хато ҳисоб мешавад, на маълумот дар код if (!response.ok) throw … ҳаст 3 Ҳолати loading : то дархост меравад — нишондиҳанда, майдон ё тугма иҷозат намедиҳанд дархости дукарата фиристода шавад Slow 3G-ро дар DevTools фаъол мекунем 4 Ҳолати error : паёми фаҳмо ва тугмаи «Такрор» (такрор); барнома намеафтад Offline-ро дар DevTools фаъол мекунем 5 Ҳолати empty : «Ҳеҷ чиз ёфт нашуд» ба ҷои экрани холӣ дархости бемаъно ворид мекунем 6 Ҷустуҷӯ ё интихоб (аз рӯи вариант) бо debounce ё тугмаи возеҳ; дархости холӣ ба сервер намеравад зуд менависем: дар Network на зиёда аз як дархост 7 Ҷавоби кӯҳна ҷавоби тозаро намепӯшонад (ҳисобкунаки дархостҳо ё AbortController) дархостро зуд иваз мекунем — дар экран охирин аст, на пеш аз охирин 8 Код ба модулҳои ES тақсим шудааст: api.js, ui.js (ё render.js), main.js сохтори папкаи src/ 9 Лоиҳа дар Vite: npm run dev оғоз мешавад, npm run build бе хато анҷом меёбад дар ҳимоя иҷро мекунем
Бонусҳо — пас аз MVP
Скелетонҳо ба ҷои калимаи «Боркунӣ…» (блокҳои хокистарӣ дар зери кортаҳо).
Кэш -и дархостҳои охирин: ҳамон дархост бори дуюм ба шабака намеравад.
Таймаути дархост тавассути Promise.race ё AbortController бо паёми худӣ.
Таърихи ҷустуҷӯ ё интихобшудаҳо дар localStorage.
Такрори худкор ҳангоми хато: то се кӯшиш бо таваққуф.
Мавзӯи торик бо нигоҳ доштани интихоб.
Саҳифабандӣ ё тугмаи «Бештар нишон додан» (limit ва skip дар dummyjson).
Маслиҳат
Бонус танҳо дар сурате қадр карда мешавад, ки шумо ҳар сатри онро фаҳмонда тавонед. Як кэши оддӣ, ки шумо мефаҳмед, аз се порчаи «сеҳрноки» чати ЗС беҳтар аст.
03 Лоиҳа чӣ тавр баҳо дода мешавад (0–100)
Лоиҳаи хурд аз рӯи шкалаи 0–100 баҳо дода мешавад, чунон ки дар қоидаҳои курс навишта шудааст. Баҳо аз ҳашт меъёр ҷамъ мешавад:
Меъёр Холҳо Ҳадди аксарро мегузорем, агар… Қисман, агар… Функсионалии MVP 20 барнома вазифаи варианти интихобшударо аз аввал то охир ҳал мекунад, дар консол хатои сурх нест сенарияи асосӣ кор мекунад, аммо хатогиҳо ҳастанд ё як қисми бандҳо нест fetch ва async/await 20 дархости ҳақиқӣ ба API-и оммавӣ, await дар ҷои даркорӣ меистад, response.ok санҷида мешавад, ҷавоб тавассути await response.json() таҳлил мешавад, хатоҳоро try/catch мегирад дархост кор мекунад, аммо 404 хато ҳисоб намешавад ё try/catch расмист Ҳолатҳои loading / error / empty 15 ҳар се ҳолат ҳаст, аз як объекти ҳолат иваз мешаванд, «Такрор» ҳаст, дархости дукарата ғайриимкон аст яке-дуи аз се ҳаст, ё ҳолатҳо «часпида мемонанд» (пас аз хато маълумоти кӯҳна мемонад) Debounce ва назорати дархостҳо 10 дархостҳо бо debounce маҳдуданд, дархости холӣ фиристода намешавад, ҷавоби кӯҳна ҷавоби тозаро намепӯшонад debounce ҳаст, аммо рақобати ҷавобҳо ҳал нашудааст Модулҳо ва сохтор 10 модулҳои ES бо сарҳадҳои фаҳмо (api ба DOM даст намезанад, ui ба шабака намеравад), функсияҳои кӯтоҳ, такрор ва коди мурда нест модулҳо ҳастанд, аммо «ҳама дар main.js» ё функсияҳои ҳаюло Ҷамъбаст ва репозиторий 5 npm run build мегузарад, репозиторийи оммавӣ, README бо скриншот, ≥ 5 commit-и бомаъноҷамъбаст кор мекунад, аммо README холӣ ё commit «ҳама як порча» Интерфейс 5 ботартиб, дар телефон хонда мешавад (320–400 px), :hover ва :focus ҳаст, тугмаҳо ҳангоми дархост қуфл мешаванд кор мекунад, аммо монанди нусхаи пешакӣ менамояд Ҳимоя 15 дар 5 дақиқа ҷо шуданд, сенарияро нишон доданд (аз ҷумла хато ва натиҷаи холӣ), порчаҳои асосиро фаҳмониданд ва ба саволҳо ҷавоб доданд бо суханони умумӣ мефаҳмонед, дар «ин сатрро фаҳмон» гум мешавед ҲАМАГӣ 100
Бонусҳо то +5 хол илова мекунанд, вале натиҷа аз 100 зиёд шуда наметавонад.
Чӣ холҳоро кам мекунад
Коди худро фаҳмонда наметавонед — дар меъёре, ки қисми нофаҳмо ба он тааллуқ дорад, холҳоро гум мекунед.
Маълумот «сахт дар код навишта шудааст» ба ҷои дархости ҳақиқӣ — меъёри «fetch ва async/await» 0 мегирад.
Дар муҳлат супурда нашуд — то −10 хол, бо мувофиқа бо муаллим.
Код пурра аз донишҷӯи дигар ё аз чат бе фаҳмиш нусха шудааст — 0 барои лоиҳа. Ба якдигар кумак кардан мумкин ва лозим аст, аммо ҳар кас аз они худро менависад ва мефаҳмад.
Ин ба баҳои ниҳоии курс чӣ тавр таъсир мекунад
Ҷузъи курс Вазн Чӣ тавр ҳисоб мешавад Ҳозиршавӣ 15% ҳиссаи дарсҳои ҳозиршуда Вазифаҳои хонагӣ 30% холи миёна барои 24 вазифаи хонагӣ (0–10) Лоиҳаҳои хурд (2 адад) 25% миёна барои лоиҳаи хурди 1 ва 2 (0–100) Лоиҳаи ниҳоӣ 30% ҳимоя дар дарси 21 (0–100)
Барои сертификат бояд ҳарду лоиҳаи хурдро супурд . Кори назоратии №2 — санҷиши алоҳидаи дониш: он нишон медиҳад, ки шумо рамзи ғайримуттаҳидро бе ЗС мефаҳмед, ва бо муаллим таҳлил мешавад (ниг. қисми 11).
Холҳо Баҳо 90–100 Аъло 75–89 Хуб 60–74 Қаноатбахш камтар аз 60 Аттестатсия нашудааст
04 Таҷзия: лоиҳаро якҷоя бо ЗС ба қисмҳо тақсим мекунем
Лоиҳа бо API аз якумӣ хатарноктар аст: шабака, интизорӣ ва хатоҳо пайдо шуданд, ки «бо фармоиш» такрор намешаванд. Барои ҳамин нақша махсусан муҳим аст. Ғоя ҳамон аст, ки дар дарси 12: аввал қадамҳо, баъд код , ва ҳар қадам натиҷаи намоён дорад. Аммо акнун дар нақша бояд қадамҳои алоҳида барои ҳар ҳолат (loading, error, empty) ва барои ҷойҳои «хатарнок» бошад: дархости аввал, рақобати ҷавобҳо, ҷамъбаст.
Монандӣ аз ҳаёт
Сафар бо маршрутка аз Душанбе ба Хуҷанд: бояд пешакӣ истгоҳҳо, вақти роҳ ва варианти эҳтиётиро донист, агар роҳро бандад. «Ба ягон тарз меравам» — роҳ ба ҳеҷ ҷо. Нақша бо варианти эҳтиётӣ — ин ҳолатҳои error ва «Такрор»-и шумост.
Блоки ЗС: вазифаи калон — маълум нест аз куҷо оғоз кардан
ЗС рӯйхати қадамҳоро хуб пешниҳод мекунад, аммо тартиб, зиёдатӣ ва баҳодиҳии вақтро шумо месанҷед . Дархостро аз рӯи формулаи курс тартиб диҳед: контекст → вазифа → маҳдудиятҳо → формати ҷавоб → санҷиш.
бо JS барномаи обуҳаво бисозНусха бардоштан
Контекст: ман донишҷӯи курси JavaScript ҳастам, лоиҳаи таълимии «обуҳаво дар шаҳрҳои Тоҷикистон»-ро бо JS-и тоза + Vite месозам, бе фреймворкҳо. API: open-meteo (бе калид). Аллакай медонам: fetch, async/await, try/catch, ҳолатҳои loading/error/empty, debounce, модулҳои ES.
Вазифа: лоиҳаро ба 10–14 қадам, ҳар кадом 20–40 дақиқа, бо тартиби иҷро тақсим кун.
Маҳдудиятҳо: бе китобхонаҳо; модулҳои api.js, ui.js, main.js; дар MVP — интихоби шаҳр, дархост, се ҳолат, тугмаи «Такрор», муҳофизат аз ҷавобҳои кӯҳна. Бонусҳо — рӯйхати алоҳида дар охир. Код нанавис.
Формати ҷавоб: рӯйхати рақамгузорӣшуда. Барои ҳар қадам: ном, пас аз он чӣ бояд кор кунад, баҳои вақт бо дақиқа.
Санҷиш: пас аз рӯйхат 3 ҷойро номбар кун, ки навомӯз дар кор бо fetch бештар хато мекунад, ва чӣ тавр онҳоро пай бурдан мумкин аст.Нусха бардоштан
Дархости аввал маҷмӯи тасодуфии калимаҳо ё фавран тамоми кодеро медиҳад, ки шумо фаҳмонида наметавонед. Дуюм — нақшае, ки бо он кор кардан мумкин аст. Аммо ин танҳо нусхаи пешакӣ аст. Мисоли нақша пас аз таҳрири шумо:
Мисоли нақша барои варианти Б (≈ 5 соат)
№ Қадам Вақт Пас аз он чӣ кор мекунад 1 Лоиҳаи Vite, сохтори src/api.js, ui.js, main.js 20 дақ npm run dev саҳифаи холиро мекушояд2 Нишонагузорӣ: интихоби шаҳр, блоки натиҷа, блоки ҳолат 25 дақ саҳифа мисли барнома менамояд, аммо «мурда» аст 3 api.js: getWeather(city) бо fetch ва санҷиши ok35 дақ функсияро аз консол даъват карда, маълумотро дидан мумкин аст 4 Объекти state ва функсияи getView(state) 25 дақ ҳар ҳолат матни худро медиҳад 5 ui.js: render(state)30 дақ ҳолати дастӣ гузошташуда тасвир мешавад 6 main.js: зеркунӣ ба шаҳр → loading → success30 дақ обуҳаво дар саҳифа пайдо мешавад 7 Шохаи error + тугмаи «Такрор» 30 дақ дар реҷаи Offline — хато, пас аз «Такрор» ҳама кор мекунад 8 Ҳолати empty (шаҳр бе маълумот) ва қуфл кардани тугмаҳо ҳангоми дархост 25 дақ зеркунии дукарата ду дархост эҷод намекунад 9 Муҳофизат аз ҷавобҳои кӯҳна (requestId) 25 дақ иваз кардани зуд-зуди шаҳрҳо охиринро нишон медиҳад 10 Услубҳо, версияи мобилӣ, фокус 35 дақ дар 360 px хуб менамояд 11 Санҷиши дастӣ: Slow 3G, Offline, маълумоти партов 30 дақ дар консол хато нест 12 npm run build, санҷиши npm run preview20 дақ ҷамъбаст аз папкаи dist кор мекунад 13 README, скриншот, репозиторий 30 дақ лоиҳа тавассути истинод дастрас аст
Бо ҷавоби ЗС чӣ кор мекунед — қадам ба қадам
Зиёдатиро хат занед. «React-ро пайваст кун», «Redux-ро танзим кун», «сервери худро бинавис» — ба лоиҳаи мо дахл надорад.
Тартибро санҷед. Ҳолати error-ро пеш аз он ки худи state бошад, тасвир кардан мумкин нест. Ҳар қадам ба қадамҳои пешини тайёр такя мекунад.
Вақтро худатон баҳо диҳед. ЗС суръати шуморо намедонад: баҳои ӯро ба 1.5 зарб кунед. Қадаме, ки аз 40 дақиқа дарозтар аст — тақсим кунед.
Ҳар қадам натиҷаи намоён медиҳад. «Бо API фаҳмидан» — қадам нест. «getWeather("Душанбе") ҳарорат дар консол бармегардонад» — қадам аст.
Қадамҳоро барои «обуҳавои бад» илова кунед: Offline, ҷавоби 404, натиҷаи холӣ. ЗС аксар вақт онҳоро фаромӯш мекунад — ин соҳаи масъулияти шумост.
Нақшаро дар PLAN.md сабт кунед ва иҷрошударо қайд намоед.
Амал: нақшаро бо воситаҳои JavaScript ҳисоб мекунем
ВАЗИФАИ 4.1 Лоиҳа чӣ қадар вақт мегирад осон
Массиви қадамҳо бо баҳои вақт бо дақиқа дода шудааст. Маҷмӯъро ҳисоб кунед ва сатри намуди Всего: 185 мин = 3.1 ч-ро чоп намоед. Соатҳоро то як рақами баъд аз вергул мудаввар кунед (toFixed(1)).
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const plan = [
{ title: "Разметка и стили" , min: 30 },
{ title: "Функция fetch и разбор ответа" , min: 40 },
{ title: "Состояния loading / error / empty" , min: 40 },
{ title: "Debounce для поиска" , min: 25 },
{ title: "Разбивка на модули" , min: 30 },
{ title: "Сборка Vite и проверка build" , min: 20 },
];
// маҷмӯи дақиқаҳоро ҳисоб кунед ва сатри ниҳоиро чоп намоед
Натиҷаи интизоршаванда Всего: 185 мин = 3.1 ч
Ишора 1 Маҷмӯи майдонҳои массиви объектҳоро reduce бо қимати ибтидоии 0 ҷамъ мекунад.
Ишора 2 plan.reduce((sum, step) => sum + step.min, 0). Соатҳо — ин total / 60 аст, ва .toFixed(1) як рақами баъд аз вергулро мегузорад.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 4.2 Хатарноктарин қадамҳо миёна
Дар қадамҳои хатарнок risky: true меистад. Онҳоро аз рӯи кам шудани вақт бо формати Рискованно: Название (N мин) чоп кунед, ва дар охир — Рискованных: N. Массиви аслиро тағйир додан мумкин нест.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const plan = [
{ title: "Разметка" , min: 20 , risky: false },
{ title: "Первый запрос к API" , min: 40 , risky: true },
{ title: "Обработка ошибок сети" , min: 35 , risky: true },
{ title: "Стили" , min: 25 , risky: false },
{ title: "Отмена устаревших запросов" , min: 30 , risky: true },
];
// филтр кунед, нусхаро мураттаб намоед, чоп кунед
Натиҷаи интизоршаванда Рискованно: Первый запрос к API (40 мин)
Рискованно: Обработка ошибок сети (35 мин)
Рискованно: Отмена устаревших запросов (30 мин)
Рискованных: 3
Ишора 1 filter массиви нав бармегардонад, барои ҳамин sort пас аз он plan-и аслиро дахл намекунад.
Ишора 2 Мураттабсозӣ аз рӯи камшавӣ: .sort((a, b) => b.min - a.min). Баъд forEach бо сатри-қолаб ва .length барои ҷамъбаст.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 4.3 Дақиқаҳо аз рӯи марҳалаҳо миёна
Объекти «марҳала → маҷмӯи дақиқаҳо»-ро ҷамъ кунед ва онро тавассути JSON.stringify чоп намоед. Тартиби калидҳо — аз рӯи пайдошавии аввали марҳала дар массив.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const plan = [
{ phase: "api" , min: 40 },
{ phase: "ui" , min: 30 },
{ phase: "api" , min: 35 },
{ phase: "build" , min: 20 },
{ phase: "ui" , min: 25 },
];
// const byPhase = plan.reduce(...)
// console.log(JSON.stringify(byPhase));
Натиҷаи интизоршаванда {"api":75,"ui":55,"build":20}
Ишора 1 Қимати ибтидоии reduce — объекти холии {}. Ҳамчун калид item.phase хизмат мекунад.
Ишора 2 acc[item.phase] = (acc[item.phase] || 0) + item.min; return acc;
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
05 Гармкунии 1. Ҳолатҳои дархост ва хатоҳои шабака
Ҳар дархост ба шабака дар яке аз чор ҳолат зиндагӣ мекунад: idle (ҳанӯз напурсидаанд), loading (интизорем), success (гирифтем, ва маълумот метавонад ҳам бо мазмун, ҳам холӣ бошад) ва error (нашуд). Қоидаи асосӣ: ҳамаи инҳо дар як объекти state меистанд, ва саҳифа аз он тасвир мешавад, мисли лоиҳаи №1.
Ҳолати дархост — як объект · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const state = {
status: "loading" , // "idle" | "loading" | "success" | "error"
items: [], // маълумот (ҳангоми success)
error: "" , // матни хато (ҳангоми error)
};
// барои ҳар статус — «экран»-и худ
const screens = {
idle: "Введите запрос" ,
loading: "Загрузка..." ,
success: "Показываем данные" ,
error: "Что-то пошло не так" ,
};
console.log (screens[state.status]);
Барои бе интернет машқ кардан мо серверро бо функсияи худамон иваз мекунем: он низ Promise бармегардонад ва бо таъхир ҷавоб медиҳад — айнан мисли fetch, аммо ҳар дафъа яксон.
Сервери сохта: Promise + setTimeout · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((resolve) => setTimeout (resolve, ms));
// «сервер» пас аз 20 мс ҷавоб медиҳад; ба дархости "error" меафтад
async function fakeApi (query) {
await wait (20 );
if (query === "error" ) throw new Error ("Сеть недоступна" );
return [`${query} 1` , `${query} 2` ];
}
async function main () {
console.log ("запрос..." );
const items = await fakeApi ("плов" );
console.log ("получили:" , items.join (", " ));
try {
await fakeApi ("error" );
} catch (err) {
console.log ("ошибка:" , err.message);
}
}
main ();
fetch-и ҳақиқӣ: пас аз ҷавоб чиро санҷидан лозим
fetch маккорона сохта шудааст: он танҳо дар сурате «меафтад» (промисро рад мекунад), ки умуман бо сервер алоқа кардан нашуд — шабака нест, домен ёфт нашуд. Аммо ҷавоби 404 Not Found ё 500 Server Error — ин аз нигоҳи fetch ҷавоби муваффақ аст: сервер ҷавоб дод-ку! Барои ҳамин пас аз await fetch(...) ҳамеша response.ok-ро санҷед.
Қолаби дархост — онро дар лоиҳа истифода баред
async function getJson (url) {
const response = await fetch (url); // 1. ҷавобро интизор мешавем
if (!response.ok) { // 2. 404 / 500 — ҳам хато
throw new Error (`HTTP ${response.status}` );
}
return await response.json (); // 3. таҳлили JSON-ро интизор мешавем
}
async function load () {
try {
const data = await getJson ("https://jsonplaceholder.typicode.com/users/1" );
console.log (data.name);
} catch (err) {
console.log ("Ошибка:" , err.message); // шабака афтод ЁКИ статус на 2xx
}
}
Дархости ҳақиқиро кӯшиш кунед. Ин ягона блоки саҳифа аст, ки ба шабака мераваду барои ҳамин санҷиши худкор надорад: натиҷа аз API вобаста аст.
Дархости зинда (интернет лозим аст) · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
async function getJson (url) {
const response = await fetch (url);
if (!response.ok) throw new Error (`HTTP ${response.status}` );
return await response.json ();
}
getJson ("https://jsonplaceholder.typicode.com/users/1" )
.then ((user) => console.log ("Пользователь:" , user.name))
.catch ((err) => console.log ("Ошибка:" , err.message));
getJson ("https://jsonplaceholder.typicode.com/users/99999" ) // чунин чиз нест → 404
.then ((user) => console.log ("Пользователь:" , user.name))
.catch ((err) => console.log ("Ошибка:" , err.message));
Монандӣ аз ҳаёт
Шумо ба Хуҷанд баста фиристодед. «Тамоман нарасонданд» (шабака нест) — мушкили фаҳмо. Аммо ҳолати дуюм ҳам ҳаст: бастаро курьер қабул кард, аммо дар нуқтаи расонидан гуфтанд «чунин нишонӣ нест» (404). Курьер кор кард, аммо натиҷа нест. response.ok — ин санҷиши «курьер омад ё не» нест, балки «ӯ чӣ овард».
Се хатои классикӣ
1. await-ро пеш аз fetch ё response.json() фаромӯш кардан — ба ҷои маълумот шумо Promise мегиред. 2. response.ok-ро нагирифтан — саҳифа ҷавоби хаторо «бо муваффақият» нишон медиҳад. 3. Хаторо коркард накардан — барнома хомӯшона дар «Боркунӣ…» овезон мемонад.
Ин код хато медиҳад · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((resolve) => setTimeout (resolve, ms));
const fakeFetch = async () => { await wait (10 ); return { ok: true , json: async () => ({ name: "Плов" }) }; };
async function load () {
const response = fakeFetch (); // await-ро фаромӯш кардем
const data = await response.json (); // TypeError: response.json is not a function
console.log (data.name);
}
load ().catch ((err) => console.log ("Ошибка:" , err.message));
Муфассалтар хонед: learn.javascript.ru — Fetch · MDN — Response.ok · learn.javascript.ru — try…catch
Амал: мустаҳкам мекунем
ВАЗИФАИ 5.1 Экран барои ҳар ҳолат осон
getView(state)-ро анҷом диҳед. Қоидаҳо: idle → Введите запрос; loading → Загрузка...; error → Ошибка: <матн>; success бо рӯйхати холӣ → Ничего не найдено, вагарна Найдено: N.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
function getView (state) {
// анҷом диҳед
}
const states = [
{ status: "idle" , items: [], error: "" },
{ status: "loading" , items: [], error: "" },
{ status: "success" , items: [], error: "" },
{ status: "success" , items: [{ id: 1 }, { id: 2 }], error: "" },
{ status: "error" , items: [], error: "Сеть недоступна" },
];
states.forEach ((s) => console.log (getView (s)));
Натиҷаи интизоршаванда Введите запрос
Загрузка...
Ничего не найдено
Найдено: 2
Ошибка: Сеть недоступна
Ишора 1 Навиштани занҷири return-ҳои барвақтӣ қулай аст: if (state.status === "idle") return "…"; ва ғайра.
Ишора 2 Барои success state.items.length === 0-ро санҷед. Барои error сатри қолабиро бо state.error истифода баред.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 5.2 loadResults: loading → success / error миёна
async function loadResults(api, query, onChange)-ро нависед. Аввал он onChange-ро бо ҳолати { status: "loading", items: [], error: "" } даъват мекунад. Баъд api(query)-ро интизор мешавад: ҳангоми муваффақият onChange-ро бо success ва items-и гирифташуда, ҳангоми хато — бо error ва матни err.message даъват мекунад (items — массиви холӣ). Хато ба берун намеафтад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((r) => setTimeout (r, ms));
const okApi = async (q) => { await wait (10 ); return [`${q}-1` , `${q}-2` ]; };
const badApi = async () => { await wait (10 ); throw new Error ("Сервер упал" ); };
// async function loadResults(api, query, onChange) { ... }
const log = (s) => console.log (`[${s.status}] items=${s.items.length} error="${s.error}"` );
async function main () {
await loadResults (okApi, "плов" , log);
await loadResults (badApi, "плов" , log);
}
main ();
Натиҷаи интизоршаванда [loading] items=0 error=""
[success] items=2 error=""
[loading] items=0 error=""
[error] items=0 error="Сервер упал"
Ишора 1 Чорчӯба: onChange-ро бо loading даъват кардем, баъд try { const items = await api(query); … } catch (err) { … }.
Ишора 2 Дар catch: onChange({ status: "error", items: [], error: err.message });. await-ро пеш аз api(query) фаромӯш накунед.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 5.3 Хатогиро ёбед: fetch бе await ва бе ok миёна
Функсияи getTitle бояд сарлавҳаро баргардонад, ва барои нишонӣ, ки 404 ҷавоб медиҳад, — сатри Ошибка: HTTP 404. Ҳоло он коре мекунад, ки лозим нест. Се хаторо ёбед.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const fakeFetch = (url) => new Promise ((resolve) => setTimeout (() => {
if (url.endsWith ("/missing" )) {
resolve ({ ok: false , status: 404 , json: async () => ({ message: "Not Found" }) });
} else {
resolve ({ ok: true , status: 200 , json: async () => ({ title: "Плов" }) });
}
}, 10 ));
async function getTitle (url) {
try {
const response = fakeFetch (url);
const data = response.json ();
return data.title;
} catch (err) {
return "Ошибка: " + err.message;
}
}
async function main () {
console.log (await getTitle ("/dishes/1" ));
console.log (await getTitle ("/dishes/missing" ));
}
main ();
Натиҷаи интизоршаванда Плов
Ошибка: HTTP 404
Ишора 1 Бо ҳамин ҳол иҷро кунед: ҳарду даъват як хатои якхела дар бораи json медиҳанд. Яъне response — ҷавоб нест, чизи дигар аст. Чӣ?
Ишора 2 await пеш аз fakeFetch(url) ва пеш аз response.json() лозим аст, ва дар байни онҳо — if (!response.ok) throw new Error(`HTTP ${response.status}`);.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 5.4 Рақобати ҷавобҳо: дархости охирин мепирӯзад душвор
Корбар зуд «п», баъд «пл» менависад. Ҷавоб ба «п» аз ҷавоб ба «пл» (10 мс) суст (50 мс) меояд ва натиҷаи тозаро мепӯшонад. onInput(q)-ро тавре анҷом диҳед, ки ба state.text танҳо ҷавоб ба дархости охирин афтад. Ғоя: ҳар дархост рақами худро дорад; ҷавобро танҳо дар сурате татбиқ мекунем, ки рақам кӯҳна нашуда бошад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const delays = { "п" : 50 , "пл" : 10 };
const search = (q) => new Promise ((resolve) =>
setTimeout (() => resolve (`результаты для "${q}"` ), delays[q]));
const state = { text: "" };
let latestId = 0 ;
async function onInput (q) {
// анҷом диҳед: рақами дархост, await search(q), танҳо ҷавоби тозаро татбиқ кунед
// ҳангоми татбиқ console.log("применён: " + q)-ро чоп кунед
}
onInput ("п" );
onInput ("пл" );
setTimeout (() => console.log (state.text), 100 );
Натиҷаи интизоршаванда применён: пл
результаты для "пл"
Ишора 1 Дар аввали функсия: const myId = ++latestId;. Тағйирёбандаи myId рақами маҳз ҳамин даъватро ба ёд мегирад.
Ишора 2 Пас аз const text = await search(q); if (myId !== latestId) return;-ро санҷед — ин ҷавоби кӯҳна аст. Вагарна state.text = text-ро нависед ва сатрро чоп кунед.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
06 Гармкунии 2. Debounce, кэш ва таймаут
Агар барои ҳар ҳарфи пахшшуда дархост фиристем, сервер даҳҳо муроҷиати зиёдатӣ мегирад, ва экран милт-милт мекунад. Debounce инро ҳал мекунад: функсия танҳо вақте кор мекунад, ки корбар барои вақти додашуда хомӯш шуд . Ҳар даъвати нав таймерро аз сифр мекунад ва навашро оғоз менамояд.
debounce: пас аз таваққуф кор мекунад · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
function debounce (fn, ms) {
let timer;
return (... args) => {
clearTimeout (timer); // таймери гузаштаро бекор кардем
timer = setTimeout (() => fn (... args), ms); // навашро оғоз кардем
};
}
const search = debounce ((q) => console.log ("запрос:" , q), 30 );
search ("п" );
search ("пл" );
search ("плов" ); // танҳо ҳамин даъват кор мекунад, пас аз 30 мс
Монандӣ аз ҳаёт
Лифт дар офис намеравад, то даме ки касе ба он медарояд: ҳар даромада таймери баста шудани дарро «аз нав мекунад». Дарҳо танҳо вақте баста мешаванд, ки якчанд сония касе надаромад. Debounce — ҳамон дарҳост.
Модулҳо ва ҷамъбаст: чӣ дар куҷост
Дар лоиҳаи Vite код дар якчанд файл зиндагӣ мекунад — модулҳои ES . Ҳар файл он чизеро, ки дигарон лозим доранд, экспорт мекунад (export) ва бегонаро import менамояд (import). Қоидаи хуби сарҳадҳо: api дар бораи DOM намедонад, ui дар бораи шабака намедонад, main онҳоро пайваст мекунад .
Сохтори лоиҳа
product-search/
├─ index.html ← подключает <script type="module" src="/src/main.js" >
├─ package.json ← скрипты dev / build / preview
├─ src/
│ ├─ api.js ← только fetch и разбор ответа
│ ├─ ui.js ← только DOM: render (state)
│ ├─ utils.js ← debounce и мелкие помощники
│ ├─ main.js ← состояние, события, связывает всё
│ └─ style.css
└─ dist/ ← появляется после npm run build (в Git не кладём)
src/api.js — танҳо маълумот, бе DOM
export async function searchProducts (query, signal) {
const url = `https://dummyjson.com/products/search?q=${encodeURIComponent(query)}&limit=10` ;
const response = await fetch (url, { signal });
if (!response.ok) throw new Error (`HTTP ${response.status}` );
const data = await response.json ();
return data.products;
}
src/main.js — модулҳоро пайваст мекунад
import { searchProducts } from "./api.js" ;
import { render } from "./ui.js" ;
import { debounce } from "./utils.js" ;
const state = { status: "idle" , items: [], error: "" };
// … ҳодисаи input → debounce(search, 400) → searchProducts → render(state)
Терминал
npm create vite@latest product-search -- --template vanilla
cd product-search
npm install
npm run dev # режим разработки, адрес вида http://localhost:5173
npm run build # собирает проект в папку dist
npm run preview # открывает собранную версию — проверьте её перед защитой
Хатои маъмул
Танҳо npm run dev-ро санҷидан. Ҷамъбаст сахттар аст: хатои имлоӣ дар роҳи import (./Api.js ба ҷои ./api.js) дар компютери шумо метавонад кор кунад, аммо npm run build меафтад. Пеш аз ҳимоя ҳамеша build ва preview-ро иҷро кунед.
Муфассалтар хонед: learn.javascript.ru — модулҳо · learn.javascript.ru — Promise API · MDN — AbortController
Амал: мустаҳкам мекунем
ВАЗИФАИ 6.1 debounce-ро нависед миёна
debounce(fn, ms)-ро нависед: функсияеро бармегардонад, ки fn-ро бо аргументҳои охирин танҳо пас аз таваққуф дар ms миллисония даъват мекунад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
// function debounce(fn, ms) { ... }
const calls = [];
const search = debounce ((q) => { calls.push (q); console.log ("запрос:" , q); }, 30 );
search ("п" );
search ("пл" );
search ("плов" );
console.log ("сразу:" , calls.length);
setTimeout (() => search ("чой" ), 80 );
setTimeout (() => console.log ("всего запросов:" , calls.length), 150 );
Натиҷаи интизоршаванда сразу: 0
запрос: плов
запрос: чой
всего запросов: 2
Ишора 1 Таймер дар тағйирёбандае дар берун аз функсияи баргардонидашаванда нигоҳ дошта мешавад (let timer;), то ки он байни даъватҳо «ба ёд монад».
Ишора 2 Дар дохили функсияи баргардонидашаванда: clearTimeout(timer); timer = setTimeout(() => fn(...args), ms);
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 6.2 Кэши дархостҳо миёна
makeCached(api)-ро нависед: функсияи ғайримуттаҳид (async) бармегардонад, ки дархостро ба намуди trim().toLowerCase() меорад, ва агар чунин дархост аллакай буд — ҷавоби нигоҳдошташударо бе муроҷиат ба api медиҳад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((r) => setTimeout (r, ms));
let apiCalls = 0 ;
const api = async (q) => { apiCalls++; await wait (10 ); return q.toUpperCase (); };
// function makeCached(api) { ... }
const cached = makeCached (api);
async function main () {
console.log (await cached ("Плов" ));
console.log (await cached (" плов " ));
console.log (await cached ("чой" ));
console.log ("вызовов API:" , apiCalls);
}
main ();
Натиҷаи интизоршаванда ПЛОВ
ПЛОВ
ЧОЙ
вызовов API: 2
Ишора 1 const cache = new Map();-ро дар берун аз функсияи баргардонидашаванда эълон кунед. Калид — дархости муътадилшуда.
Ишора 2 if (cache.has(key)) return cache.get(key); вагарна const value = await api(key); cache.set(key, value); return value;
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 6.3 Ҷавоби API → кортаҳо миёна
API объекти маҳсулотро баргардонд. toCards(data)-ро нависед: танҳо маҳсулоти мавҷударо (stock > 0) монед, аз рӯи нарх бо тартиби афзуда мураттаб кунед (массиви аслиро тағйир надиҳед), сатрҳои намуди Чехол — 50 сом. (★ 4.8)-ро баргардонед. Рейтинг — бо як рақами баъд аз вергул.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const apiData = {
total: 4 ,
products: [
{ id: 1 , title: "Телефон" , price: 2500 , rating: 4.46 , stock: 5 },
{ id: 2 , title: "Наушники" , price: 300 , rating: 3.9 , stock: 0 },
{ id: 3 , title: "Чехол" , price: 50 , rating: 4.8 , stock: 20 },
{ id: 4 , title: "Зарядка" , price: 120 , rating: 4.1 , stock: 7 },
],
};
// function toCards(data) { ... }
const cards = toCards (apiData);
cards.forEach ((c) => console.log (c));
console.log (cards.length, apiData.products[0 ].title);
Натиҷаи интизоршаванда Чехол — 50 сом. (★ 4.8)
Зарядка — 120 сом. (★ 4.1)
Телефон — 2500 сом. (★ 4.5)
3 Телефон
Ишора 1 Занҷир: data.products.filter(...) → .sort(...) → .map(...). filter аллакай нусха месозад, барои ҳамин массиви аслиро sort тағйир намедиҳад.
Ишора 2 Деструктуркунӣ дар map қолабро содда мекунад: ({ title, price, rating }) => `${title} — ${price} сом. (★ ${rating.toFixed(1)})`.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 6.4 Таймаути дархост тавассути Promise.race душвор
withTimeout(promise, ms)-ро нависед: агар promise дар ms миллисония ба анҷом нарасид — натиҷа бо хатои Таймаут рад мешавад, вагарна қимати промис баргардонида мешавад. Promise.race-ро истифода баред.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((r) => setTimeout (r, ms));
const fast = () => wait (20 ).then (() => "быстро" );
const slow = () => wait (200 ).then (() => "медленно" );
// function withTimeout(promise, ms) { ... }
async function main () {
for (const fn of [fast, slow]) {
try {
console.log (await withTimeout (fn (), 100 ));
} catch (err) {
console.log ("Ошибка:" , err.message);
}
}
}
main ();
Натиҷаи интизоршаванда быстро
Ошибка: Таймаут
Ишора 1 Promise.race([a, b]) ҳамон тавр ба анҷом мерасад, ки ягон аз промисҳое, ки аввал ба анҷом расид. Промиси дуюмро «таймер-бомба» кунед.
Ишора 2 new Promise((_, reject) => setTimeout(() => reject(new Error("Таймаут")), ms)) — ин «бомба» аст.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
07 Санҷиш пеш аз ҳимоя: package.json ва ҷамъбаст
Вақте npm run build-ро иҷро мекунед, Vite фармони build-ро дар бахши scripts-и файли package.json меёбад, ҳамаи модулҳоро ба якчанд файл ҷамъ мекунад ва ба папкаи dist мегузорад. Маҳз ҳамин папкаро ба хостинг мегузоранд. Дар .gitignore бояд node_modules ва dist бошанд: онҳоро дар репозиторий нигоҳ доштан лозим нест, бо фармонҳои npm install ва npm run build барқарор мешаванд.
Чек-листи «барои ҳимоя омодаам»
☐ npm install дар папкаи тоза мегузарад · ☐ npm run dev барномаро мекушояд · ☐ npm run build бе хато ва огоҳӣ · ☐ npm run preview ҳамонро нишон медиҳад · ☐ дар консоли браузер сурх нест · ☐ дар Network дархостҳо ба API-и ҳақиқӣ мераванд · ☐ дар Offline хато нишон дода мешавад, на экрани сафед.
Амал: мустаҳкам мекунем
ВАЗИФАИ 7.1 package.json-ро бихонед осон
Матни файли package.json дода шудааст. Онро тавассути JSON.parse таҳлил кунед ва ҳар скриптро бо формати npm run ном → фармон чоп намоед, баъд Зависимостей: N — дар devDependencies ҳамагӣ чанд баста ҳаст.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const text = `{
"name": "product-search",
"private": true,
"scripts": { "dev": "vite", "build": "vite build", "preview": "vite preview" },
"devDependencies": { "vite": "^7.0.0" }
}` ;
// JSON-ро таҳлил кунед ва натиҷаро чоп намоед
Натиҷаи интизоршаванда npm run dev → vite
npm run build → vite build
npm run preview → vite preview
Зависимостей: 1
Ишора 1 const pkg = JSON.parse(text); — акнун pkg.scripts объекти оддӣ аст.
Ишора 2 Ҷуфтҳои «калид — қимат»-ро Object.entries(pkg.scripts) медиҳад. Шумораи бастаҳо — Object.keys(pkg.devDependencies).length.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
08 Қолаби ибтидоӣ: ҷустуҷӯ бо ҳолатҳо
Дар зер — скелети барнома бо ҷустуҷӯ дар майдончаи озмоишӣ. То ки натиҷа ҳамеша яксон бошад, ба ҷои сервери ҳақиқӣ дар он «сохта» (fakeSearch) истифода шудааст; ва дар паҳлӯ realSearch бо fetch-и ҳақиқӣ меистад — дар лоиҳаи худ шумо онро бо як сатр ҷойгузин мекунед. Код ба блокҳо бо ҳамон тартибе тақсим шудааст, ки шарҳ додани он дар ҳимоя қулай аст: «сервер» → ҳолат → DOM ва тасвир → ҷустуҷӯ → ҳодисаҳо .
«Сервер». Маълумот ва функсияҳое, ки промис бармегардонанд: сохта ва ҳақиқӣ.
Ҳолат. Як объекти { status, items, error } ва ҳисобкунаки дархостҳои latestId.
Тасвир. render() интерфейсро аз state месозад. Дигар касе ба DOM даст намезанад.
Ҷустуҷӯ. search(query): loading → success ё error, ҷавобҳои кӯҳна нодида гирифта мешаванд.
Ҳодисаҳо. Майдони ворид бо debounce.
▶ Иҷро кардан -ро пахш кунед: худсанҷии поён чоп мекунад, ки ҳоло чӣ кор намекунад. Вазифаи шумо — чор қайди TODO.
Амал: барномаи ибтидоиро месозем
ВАЗИФАИ 8.1 TODO-ро анҷом диҳед — ва ҷустуҷӯ кор мекунад душвор
Дар script.js чор қайдро амалӣ кунед: 1) debounce, 2) getStatusText, 3) search (дархости холӣ ба сервер намеравад; ҳолатҳо; муҳофизат аз ҷавобҳои кӯҳна; хато ба берун намеафтад), 4) коркунандаи input бо debounce. Блоки худсанҷии поён худаш дар майдон «менависад» ва натиҷаро ба консол мебарорад. Вақте ҳама тайёр аст, дар консол бояд дақиқан ҳамон чизе бошад, ки дар «Натиҷаи интизоршаванда». Блоки худсанҷиро ба лоиҳаи худ нусха накунед.
Ҷустуҷӯи ибтидоии маҳсулот · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
index.html style.css script.js
< main class ="app" >
< h1 > Поиск товаров</ h1 >
< input id ="q" placeholder ="Например: телефон" autocomplete ="off" >
< p id ="status" class ="status" > </ p >
< ul id ="results" > </ ul >
</ main >
.app { max-width : 420px ; margin : 0 auto; font-family : system-ui, sans-serif; }
h1 { font-size : 22px ; margin : 0 0 12px ; }
input { width : 100 %; box-sizing : border-box; padding : 10px 12px ; border : 1px solid #c7ccd6 ; border-radius : 8px ; font : inherit; }
.status { color : #5b6477 ; min-height : 1.4em ; }
.status[data-status="error" ] { color : #d1344f ; }
.status[data-status="loading" ] { color : #1f6feb ; }
ul { list-style : none; padding : 0 ; margin : 0 ; }
li { display : flex; justify-content : space-between; padding : 8px 4px ; border-bottom : 1px solid #e6e9f0 ; }
li .price { color : #5b6477 ; }
// ===== 1. «Сервер» =====
const PRODUCTS = [
{ id: 1 , title: "Телефон Samsung" , price: 2500 },
{ id: 2 , title: "Телевизор LG" , price: 4200 },
{ id: 3 , title: "Ноутбук Acer" , price: 5100 },
{ id: 4 , title: "Наушники Sony" , price: 600 },
{ id: 5 , title: "Чехол для телефона" , price: 50 },
{ id: 6 , title: "Зарядка для телефона" , price: 120 },
{ id: 7 , title: "Клавиатура" , price: 180 },
{ id: 8 , title: "Мышь" , price: 90 },
];
const wait = (ms) => new Promise ((resolve) => setTimeout (resolve, ms));
// сервери сохта: пас аз 60 мс ҷавоб медиҳад; ба дархости "error" меафтад
async function fakeSearch (query) {
await wait (60 );
if (query === "error" ) throw new Error ("Сеть недоступна" );
const q = query.trim ().toLowerCase ();
return PRODUCTS.filter ((p) => p.title.toLowerCase ().includes (q));
}
// сервери ҳақиқӣ — дар лоиҳаи худ searchApi-ро ба он иваз кунед
async function realSearch (query) {
const url = `https://dummyjson.com/products/search?q=${encodeURIComponent(query)}&limit=10` ;
const response = await fetch (url);
if (!response.ok) throw new Error (`HTTP ${response.status}` );
const data = await response.json ();
return data.products;
}
const searchApi = fakeSearch;
// ===== 2. Ҳолат =====
let state = { status: "idle" , items: [], error: "" }; // "idle" | "loading" | "success" | "error"
let latestId = 0 ; // рақами дархости охирин
const DEBOUNCE_MS = 40 ;
function setState (patch) {
state = { ... state, ... patch };
render ();
}
// TODO 1: debounce — fn-ро танҳо пас аз таваққуф дар ms миллисония даъват мекунад
function debounce (fn, ms) {
return fn;
}
// TODO 2: матни статус аз рӯи ҳолат:
// idle → "Введите запрос", loading → "Загрузка...", error → "Ошибка: МАТН",
// success: холӣ → "Ничего не найдено", вагарна → "Найдено: N"
function getStatusText (s) {
return "" ;
}
// ===== 3. DOM ва тасвир =====
const input = document.querySelector ("#q" );
const statusEl = document.querySelector ("#status" );
const list = document.querySelector ("#results" );
function createItem (product) {
const li = document.createElement ("li" );
const name = document.createElement ("span" );
name.textContent = product.title;
const price = document.createElement ("span" );
price.className = "price" ;
price.textContent = product.price + " сом." ;
li.append (name, price);
return li;
}
function render () {
statusEl.textContent = getStatusText (state);
statusEl.dataset.status = state.status;
list.replaceChildren (); // рӯйхатро тоза кардем
state.items.forEach ((product) => list.append (createItem (product)));
}
// ===== 4. Ҷустуҷӯ =====
// TODO 3: дархости холӣ (пас аз trim) → setState idle бе муроҷиат ба сервер.
// Вагарна: рақами дархости худӣ, status "loading", await searchApi, баъд "success" ё "error".
// Агар ҳангоми интизорӣ дархости нав оғоз шуд (рақам кӯҳна шуд) — натиҷаро партоед.
async function search (query) {
}
// ===== 5. Ҳодисаҳо =====
// TODO 4: ҳангоми ҳар ворид кардан search(input.value)-ро даъват кунед, вале тавассути debounce(…, DEBOUNCE_MS)
input.addEventListener ("input" , () => {
});
render ();
// ===== Худсанҷӣ барои вазифаи 8.1 (ба лоиҳаи худ нусха накунед) =====
(async () => {
const type = (text) => {
input.value = text;
input.dispatchEvent (new Event ("input" ));
};
console.log ("старт:" , statusEl.textContent);
type ("т" ); type ("те" ); type ("тел" );
console.log ("сразу после ввода:" , statusEl.textContent);
await wait (70 );
console.log ("через 70 мс:" , statusEl.textContent);
await wait (100 );
console.log ("ответ:" , statusEl.textContent, "|" , list.children.length);
type ("zzz" );
await wait (200 );
console.log ("пусто:" , statusEl.textContent);
type ("error" );
await wait (200 );
console.log ("ошибка:" , statusEl.textContent);
type (" " );
await wait (100 );
console.log ("очистили:" , statusEl.textContent);
})();
Пешнамоиш Пӯшонидан
Барои дидани натиҷа «Иҷро кардан»-ро пахш кунед.
Натиҷаи интизоршаванда старт: Введите запрос
сразу после ввода: Введите запрос
через 70 мс: Загрузка...
ответ: Найдено: 4 | 4
пусто: Ничего не найдено
ошибка: Ошибка: Сеть недоступна
очистили: Введите запрос
Ишора 1 Қолабро бо ҳамин ҳол иҷро кунед ва баромадро бо интизоршаванда муқоиса намоед: сатрҳое, ки мувофиқат намекунанд, ишора мекунанд, ки кадом TODO-ро минбаъд ҳал кардан лозим. Аз getStatusText оғоз кунед — ин аз ҳама соддатар аст.
Ишора 2 search: const myId = ++latestId;, санҷиши дархости холӣ, setState({ status: "loading", ... }), баъд try бо await searchApi(query) ва санҷиши if (myId !== latestId) return; пас аз await (ва ҳамон дар catch). Коркунанда: const debouncedSearch = debounce(search, DEBOUNCE_MS); берун аз шунаванда, ва дар дохил — debouncedSearch(input.value);.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
Чӣ тавр қолабро ба лоиҳаи худ гузаронидан
Лоиҳаро дар Vite эҷод кунед (қисми 06) ва кодро ба модулҳо тақсим намоед: fakeSearch/realSearch — ба api.js, debounce — ба utils.js, getStatusText ва render — ба ui.js, ҳолат ва ҳодисаҳо — ба main.js.
Ба ҳар файл export/import илова кунед. render акнун state-ро ҳамчун аргумент мегирад — тағйирёбандаҳои глобалӣ байни модулҳо намегузаранд.
fakeSearch-ро ба realSearch иваз кунед ва дар ҷадвали Network боварӣ ҳосил намоед, ки дархостҳо ҳақиқианд.
Блоки худсанҷиро хориҷ кунед.
Агар шумо аллакай лоиҳаи худии дарсҳои 15–17-ро дошта бошед — онро напартоед, балки бо схемаи «ҳолат → render → search → ҳодисаҳо» муқоиса кунед.
09 Амал дар дарс: ревью, ҳимояҳо, кори назоратӣ
Имрӯз машғулот аз муқаррарӣ дигартар сохта шудааст: лоиҳаҳо қариб тайёранд, барои ҳамин вақт ба санҷиш, ҳимоя ва кори назоратӣ сарф мешавад. Мувофиқи нақша амал мекунем.
0–10 дақ · Санҷиши охирин. Чек-листи қисми 07: npm run build, preview, Offline, Slow 3G. Муаллим тартиби ҳимояҳоро тасдиқ мекунад.
10–30 дақ · Code review дар ҷуфтҳо. Барои ҳар лоиҳа 10 дақиқа. Ревьюер аз рӯи чек-листи поён мегузарад ва мулоҳизаҳоро сабт мекунад, муаллиф гӯш мекунад. Баъд ҷой иваз мекунед.
30–60 дақ · Ҳимояҳо. Ҳар кадом — 5 дақиқа ва як дақиқа барои иваз кардан. Дигарон гӯш мекунанд ва савол медиҳанд. Имрӯз натавонистед — дар аввали машғулоти оянда ҳимоя мекунед.
60–90 дақ · Кори назоратии №2. 30 дақиқа, барои ҳама якбора, бе ЗС . Тафсилот — дар қисми 11. Таҳлили хатоҳои маъмул — дар охир.
Агар лоиҳа ҳанӯз тайёр нест
Бонусҳо илова накунед. Қолаби ибтидоиро аз қисми 08 кушоед, чор TODO-ро анҷом диҳед, build-ро санҷед ва README илова кунед. Лоиҳаи содда, ки кор мекунад, аз лоиҳаи мураккаби нопурра беҳтар аст.
Code review: чек-листи ревьюер
Code review — ин вақте аст, ки як таҳиягар кодро аз таҳиягари дигар пеш аз он ки «ба олам барояд» мехонад. На имтиҳон ва на ҷустуҷӯи гунаҳкор: нигоҳи тоза он чизеро мебинад, ки муаллиф дигар пай намебарад. Формулаи мулоҳиза: дар куҷо (файл ва сатр) → чӣ мебинам → чаро муҳим аст → пешниҳод (беҳтараш бо савол).
Мешиканем (иҷро)
☐ Реҷаи Offline: барнома хато ва «Такрор»-ро нишон медиҳад, на экрани сафед
☐ Slow 3G: нишондиҳанда намоён аст, тугмаҳо иҷозат намедиҳанд дархости дукарата фиристода шавад
☐ Дархости бемаъно: паёми «Ҳеҷ чиз ёфт нашуд»
☐ Зуд менависем: дар Network на зиёда аз як дархост барои як «таваққуф»
☐ Дархостро зуд иваз мекунем: дар экран ҷавоб ба охирин аст, на ба пеш аз охирин
☐ Пас аз хато ва «Такрор» маълумоти кӯҳна «намечаспад»
☐ Сатри холӣ ба сервер намеравад
☐ Матн аз API ҳамчун матн нишон дода мешавад (textContent)
☐ Дар паҳноии 360 px ҳама чиз хонда мешавад; дар консол сурх нест
Код мехонем
☐ Як объекти state бо статус, на маҷмӯи парчамҳои isLoading, isError…
☐ Пас аз fetch санҷиши response.ok меистад
☐ Ҳар ҷое ки лозим аст, await ҳаст; промиси «фаромӯшшуда» нест
☐ try/catch дар гирди дархост ва паёми бомаъно, на catch-и холӣ
☐ Модулҳо: api ба DOM даст намезанад, ui ба шабака намеравад
☐ debounce як бор навишта шудааст ва аз нав истифода мешавад
☐ Сатрҳои статусҳо ба собитҳо бароварда шудаанд
☐ Коди шарҳшуда, console.log ва функсияҳои мурда нестанд
☐ Дар репозиторий node_modules ва dist нестанд
ЗС ҳамчун ревьюери дуюм — пас аз одамон, на ба ҷои онҳо
Вақте ҷуфт ба анҷом расид, кодро аз ЗС гузаронед: «Аз рӯи чек-лист санҷ: коркарди хатоҳои fetch, рақобати ҷавобҳо, сарҳадҳои модулҳо, номҳо. Танҳо мулоҳизаҳо, бе аз нав навиштани код». На ҳамаи маслиҳатҳоро қабул кунед: ҳар ислоҳро шумо бояд асоснок карда тавонед.
Муфассалтар хонед: learn.javascript.ru — ислоҳи хато дар браузер
Амал: ревью дар миниатюра
ВАЗИФАИ 9.1 Мулоҳизаи ревьюер: хато маълумотро тоза намекунад миёна
Ревьюер навишт: «Пас аз хато дар экран натиҷаҳои кӯҳна мемонанд, ва пас аз муваффақият — матни кӯҳнаи хато». applyResult-ро ислоҳ кунед: ҳангоми error — items массиви холӣ мешавад, ҳангоми success — error сатри холӣ мешавад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
function applyResult (state, result) {
if (result.error) {
return { ... state, status: "error" , error: result.error };
}
return { ... state, status: "success" , items: result.items };
}
let s = { status: "idle" , items: [], error: "" };
s = applyResult (s, { items: ["плов" , "чой" ] });
console.log (s.status, s.items.length, JSON.stringify (s.error));
s = applyResult (s, { error: "Сеть недоступна" });
console.log (s.status, s.items.length, JSON.stringify (s.error));
s = applyResult (s, { items: ["самбуса" ] });
console.log (s.status, s.items.length, JSON.stringify (s.error));
Натиҷаи интизоршаванда success 2 ""
error 0 "Сеть недоступна"
success 1 ""
Ишора 1 Ҳар ҳолат бояд пурра бошад: ҳангоми иваз шудани статус майдонҳоеро, ки ба статуси нав дахл надоранд, тоза кунед.
Ишора 2 Ба шохаи хато items: [], ва ба шохаи муваффақият — error: "" илова кунед.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 9.2 Мулоҳизаи ревьюер: хатои имлоӣ дар статус осон
Статуси «Загрузка» нишон дода намешавад — ревьюер хатои имлоиро гумон мекунад. Онро ислоҳ кунед, ва дар баробар статусҳоро ба собити STATUS (IDLE, LOADING, SUCCESS, ERROR) бароред ва онро ҳама ҷо истифода баред: ҳамин тавр хатои имлоӣ ба хатое табдил меёбад, ки муҳаррир пай мебарад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
function badge (status) {
if (status === "loadin" ) return "⏳ Загрузка" ;
if (status === "error" ) return "⚠ Ошибка" ;
if (status === "success" ) return "✓ Готово" ;
return "…" ;
}
console.log (badge ("idle" ));
console.log (badge ("loading" ));
console.log (badge ("error" ));
console.log (badge ("success" ));
Натиҷаи интизоршаванда …
⏳ Загрузка
⚠ Ошибка
✓ Готово
Ишора 1 Сатри дар шартро бо сатре, ки ҳангоми даъват мегузаронанд, муқоиса кунед: онҳо бояд то ҳарф мувофиқ бошанд.
Ишора 2 const STATUS = { IDLE: "idle", LOADING: "loading", SUCCESS: "success", ERROR: "error" }; — ва ҳама ҷо STATUS.LOADING ба ҷои сатр.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
10 Ҳимоя: 5 дақиқае, ки 15 холро ҳал мекунад
Ҳимоя — ин ҳикояи кӯтоҳ дар бораи он, ки шумо чӣ кардед ва ин чӣ тавр кор мекунад . На презентатсия ва на бозпурсӣ: бояд нишон диҳед, ки лоиҳа аз они шумост ва шумо онро мефаҳмед. Барои ҳамин ба он 15 хол аз 100 ҷудо шудааст. Дар ин ҷо шумо на танҳо «вақте ҳама хуб аст», балки «обуҳавои бад» -ро ҳам нишон медиҳед: Offline ва натиҷаи холӣ.
Сенария барои 5 дақиқа
Вақт Чӣ кор мекунед 0:00–0:30 Муаррифӣ. Бо як ибора: ин кадом барнома аст, кадом API. «Ин ҷустуҷӯи маҳсулот дар dummyjson аст: калима менависӣ — пас аз ним сония кортаҳоро мебинӣ».0:30–2:00 Намоиш. Ҷустуҷӯ → натиҷаи холӣ → Offline дар DevTools → хато ва «Такрор» → ҳама боз кор мекунад. preview-и версияи ҷамъшударо кушоед.2:00–3:30 Код. Се ҷой: getJson/api.js (fetch + ok), объекти state ва render, debounce. Бо суханони худатон шарҳ диҳед.3:30–5:00 Саволҳо. Намедонед — ростқавлона бигӯед ва тахмин кунед, ки ҷавобро чӣ тавр меҷустед.
Саволҳои маъмул ва дар бораи чӣ гуфтан лозим
async/await чист ва аз then чӣ фарқ дорад? Ин ҳамон Promise аст, аммо код аз боло ба поён хонда мешавад. await функсияро то ҷавоб «таваққуф мекунад», бе қуфл кардани саҳифа.
Барои чӣ response.ok лозим аст? Магар fetch дар 404 намеафтад? Не: fetch танҳо ҳангоми мушкили шабака рад мекунад. Ҷавоби 404/500 — «муваффақ» аст, зеро сервер ҷавоб дод. Статусро худатон бояд санҷед.
Барои чӣ await response.json(), ин ахир аллакай ҷавоб аст? Сарлавҳаҳо омаданд, аммо баданаи ҷавоб алоҳида ва ҳамчунин ғайримуттаҳид хонда мешавад.
Debounce чист ва барои чӣ дар ин ҷо лозим аст? Функсия пас аз таваққуф кор мекунад. Бе он ҳар ҳарф — дархост: сарбории зиёдатӣ ва экрани «милтилдеанда».
Рақобати ҷавобҳо чист ва шумо онро чӣ тавр ҳал кардед? Ҷавоб ба дархости кӯҳна метавонад дертар аз ҷавоб ба дархости нав расад ва онро бипӯшонад. Ҳал: рақами дархост (танҳо тозаро татбиқ мекунем) ё AbortController.
Ҳолатҳои шумо чӣ тавр сохта шудаанд? Як объекти state бо status, items, error; render аз он тасвир мекунад. Маҷмӯи парчамҳое нест, ки метавонанд бо якдигар зиддият кунанд.
Дар api.js чӣ ҳаст, дар ui.js чӣ, ва барои чӣ ин тавр? Дар api.js танҳо шабака, дар ui.js танҳо DOM, main.js пайваст мекунад. Ҳамин тавр ҳар қисмро алоҳида тағйир додан ва санҷидан мумкин аст.
npm run build чӣ кор мекунад ва дар dist чӣ меистад?Vite модулҳоро ба файлҳои барои хостинг тайёр ҷамъ мекунад. dist-ро ба Git намегузоранд: онро аз нав ҷамъ кардан мумкин аст.
ЗС-ро дар куҷо истифода кардед? Ин сатрро шарҳ диҳед. Ростқавлона бигӯед, барои чӣ (нақша, шарҳи хато, ревью) ва дар куҷо ӯ хато кард — қисми 12. Ҳар сатрро бояд бо суханони худатон шарҳ диҳед.
Маслиҳатҳо барои омодагӣ
Намоишро бо овози баланд бо секундомер такрор кунед. Offline дар DevTools → Network → «No throttling» → Offline фаъол мешавад.
Файлҳои даркориро пешакӣ кушоед , ҳуруфро калон кунед: гурӯҳ бояд кодро бубинад.
Зиёдатиро хориҷ кунед: console.log, коди шарҳшуда.
Узр наовардед («натавонистам»). Беҳтараш: «ин нест, зеро… инак ман онро чӣ тавр илова мекардам».
Амал: тамрин
ВАЗИФАИ 10.1 Ҷавобҳоро ба саволҳои ҳимоя омода кунед осон
Ба панҷ саволи боло дар бораи лоиҳаи худ бо суханони худатон, бо як-ду ҷумла ҷавоб диҳед. Ҷавобҳоро дар объект сабт кунед (инҳо ёддошт ҳастанд — санҷиши худкор нест), баъд назди ҳамсоя бо овози баланд такрор кунед. Вақте ҷавоб додед — вазифаро дастӣ қайд кунед.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const defence = {
ok: "Проверяю response.ok, потому что ..." ,
states: "" ,
debounce: "" ,
race: "" ,
ai: "" ,
};
console.log (Object.keys (defence).length + " ответов подготовлено" );
Ишора 1 Мисли ба дӯсте ҷавоб диҳед, ки кодатонро ҳаргиз надидааст: кӯтоҳ ва бо мисол аз лоиҳа.
Ишора 2 Ҷавоби хуб мушаххас аст: «дар api.js, сатри 6, пас аз fetch if (!response.ok) меистад», на «хуб, дар он ҷо чизе месанҷад».
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
11 Кори назоратии №2 · версияи озмоишӣ
🚫 Дар кори назоратӣ ЗС хомӯш аст
Кори назоратии ҳақиқӣ — 30 дақиқа, бе ЗС, бе ишораҳо , бе чат ва бе ҳамсоя. Дар зер — версияи пурраи озмоишӣ: 10 вазифа оид ба мавзӯъҳои объектҳо, async/await, fetch, коркарди хатоҳо . Дар ин қисм ишораҳо нестанд (тугмаҳои «Ишора»-ро намебинед) — мисли кори назоратии ҳақиқӣ. Бо таймер барои 30 дақиқа ҳал кунед, аз саҳифа набароед ва чати ЗС-ро накушоед.
Версияи озмоишӣ чӣ тавр мегузарад
Ҳама ростқавлона: аввал таймерро мемонед, баъд ҳал мекунед. Ҳамаи «дархостҳо» дар ин ҷо — функсияҳои сохта аз Promise ва setTimeout ҳастанд, барои ҳамин ҷавоби ҳар вазифа худкор санҷида мешавад ва аз интернет вобаста нест. Тартиби сатрҳо дар консол низ ҷузъи натиҷа аст, пас ба он бодиққат нигоҳ кунед.
Нишондиҳанда барои худсанҷӣ: 9–10 вазифа — натиҷаи аъло, 7–8 — хуб, 5–6 — қаноатбахш, камтар аз 5 — дарсҳои 13–16-ро такрор кунед ва боз кӯшиш намоед. Ҳадди расмии кори назоратии ҳақиқиро муаллим муайян мекунад.
Кори назоратии №2 · 10 вазифа · 30 дақиқа
ВАЗИФАИ 11.1 Профили донишҷӯ (деструктуркунӣ) осон
Барои ҳар донишҷӯ сатри Алишер (22) — Душанбе-ро чоп кунед. Агар шаҳр нест (address.city вуҷуд надорад) — не указан-ро чоп кунед. Деструктуркуниро истифода баред.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const students = [
{ name: "Алишер" , age: 22 , address: { city: "Душанбе" } },
{ name: "Мадина" , age: 19 , address: {} },
{ name: "Фаррух" , age: 25 , address: { city: "Худжанд" } },
];
// коди шумо
Натиҷаи интизоршаванда Алишер (22) — Душанбе
Мадина (19) — не указан
Фаррух (25) — Худжанд
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 11.2 Нархномаи чойхона (Object.entries) осон
Объекти нархҳо дода шудааст. Маҷмӯи ҳамаи нархҳоро бо формати Сумма: 36 ва гаронтарин таомро бо формати Дороже всего: плов (25) чоп кунед.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const prices = { плов: 25 , чой: 5 , самбуса: 6 };
// коди шумо
Натиҷаи интизоршаванда Сумма: 36
Дороже всего: плов (25)
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 11.3 Даромад аз рӯи шаҳрҳо (reduce ба объект) миёна
Объекти «шаҳр → маҷмӯи фармоишҳо»-ро ҷамъ кунед ва тавассути JSON.stringify чоп намоед, баъд шумораи шаҳрҳоро бо формати Городов: 2.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const orders = [
{ city: "Душанбе" , sum: 100 },
{ city: "Худжанд" , sum: 80 },
{ city: "Душанбе" , sum: 50 },
];
// коди шумо
Натиҷаи интизоршаванда {"Душанбе":150,"Худжанд":80}
Городов: 2
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 11.4 Хатогиро ёбед: await-и фаромӯшшуда миёна
Баромади Привет, Алишер! ва Длина имени: 6 интизор аст. Ҳоло код чизи бемаъно чоп мекунад. Ислоҳ кунед.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((r) => setTimeout (r, ms));
const getName = () => wait (10 ).then (() => "Алишер" );
async function greet () {
const name = getName ();
console.log (`Привет, ${name}!` );
return name.length;
}
greet ().then ((len) => console.log ("Длина имени:" , len));
Натиҷаи интизоршаванда Привет, Алишер!
Длина имени: 6
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 11.5 Ду дархости вобаста миёна
async function showProfile(id)-ро нависед: аввал корбарро гиред (api.user(id)), баъд дастаи ӯро аз рӯи user.teamId (api.team(...)) ва Мадина — Frontend-17 (12 чел.)-ро чоп кунед. Пас аз анҷоми даъват готово чоп мешавад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((r) => setTimeout (r, ms));
const api = {
user: async (id) => { await wait (10 ); return { id, name: "Мадина" , teamId: 7 }; },
team: async (teamId) => { await wait (10 ); return { id: teamId, title: "Frontend-17" , members: 12 }; },
};
// async function showProfile(id) { ... }
showProfile (1 ).then (() => console.log ("готово" ));
Натиҷаи интизоршаванда Мадина — Frontend-17 (12 чел.)
готово
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 11.6 Дархостҳои мувозӣ (Promise.all) миёна
loadAll(ids)-ро нависед: ҳамаи шаҳрҳоро якбора дархост кунед ва массиви номҳоро бо тартиби ids (на бо тартиби омадани ҷавобҳо) баргардонед. Дархостҳои пай дар пай тартиби дигари сатрҳои пришёл …-ро медиҳанд ва санҷишро намегузаранд.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const delays = { 1 : 30 , 2 : 5 , 3 : 15 };
const cities = { 1 : "Душанбе" , 2 : "Худжанд" , 3 : "Бохтар" };
const getCity = (id) => new Promise ((resolve) => setTimeout (() => {
console.log ("пришёл" , id);
resolve (cities[id]);
}, delays[id]));
// function loadAll(ids) { ... }
loadAll ([1 , 2 , 3 ]).then ((names) => console.log (names.join (", " )));
Натиҷаи интизоршаванда пришёл 2
пришёл 3
пришёл 1
Душанбе, Худжанд, Бохтар
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 11.7 getJson бо санҷиши ok миёна
getJson(url)-ро бо ёрии fakeFetch нависед: агар response.ok дурӯғ бошад — хатоеро бо матни HTTP <статус> партоед, вагарна JSON-и таҳлилшударо баргардонед. Хатоҳо аз давраи поён бо коди аллакай омода коркард мешаванд.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((r) => setTimeout (r, ms));
const fakeFetch = async (url) => {
await wait (5 );
if (url === "/users" ) return { ok: true , status: 200 , json: async () => [{ name: "Алишер" }] };
if (url === "/nope" ) return { ok: false , status: 404 , json: async () => ({}) };
return { ok: false , status: 500 , json: async () => ({}) };
};
// async function getJson(url) { ... }
async function main () {
for (const url of ["/users" , "/nope" , "/crash" ]) {
try {
const data = await getJson (url);
console.log ("OK:" , data.length);
} catch (err) {
console.log ("Ошибка:" , err.message);
}
}
}
main ();
Натиҷаи интизоршаванда OK: 1
Ошибка: HTTP 404
Ошибка: HTTP 500
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 11.8 safeLoad: натиҷа ба ҷои истисно душвор
safeLoad(task)-ро нависед: он функсияи ғайримуттаҳиди task-ро даъват мекунад ва { ok: true, data }-ро бармегардонад; ҳангоми хато — { ok: false, name: err.name, error: err.message }. Ҳисобкунаки finished бояд ҳангоми ҳар гуна анҷом афзояд (finally-ро истифода баред).
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((r) => setTimeout (r, ms));
let finished = 0 ;
// async function safeLoad(task) { ... }
const tasks = [
async () => { await wait (5 ); return [1 , 2 , 3 ]; },
async () => { await wait (5 ); throw new Error ("Сервер недоступен" ); },
async () => { await wait (5 ); throw new TypeError ("Неверный формат" ); },
];
async function main () {
for (const task of tasks) {
const result = await safeLoad (task);
console.log (result.ok ? `данные: ${result.data.length}` : `${result.name}: ${result.error}` );
}
console.log ("завершено:" , finished);
}
main ();
Натиҷаи интизоршаванда данные: 3
Error: Сервер недоступен
TypeError: Неверный формат
завершено: 3
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 11.9 retry: ҳангоми нокомӣ такрор мекунем душвор
retry(fn, times)-ро нависед: то times кӯшиш fn-ро даъват мекунад; пеш аз ҳар яке Попытка N (аз як) чоп мекунад. Агар кӯшиш муваффақ шуд — натиҷаро бармегардонад. Агар ҳама нокомоданд — хатои кӯшиши охирин -ро мепартояд.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((r) => setTimeout (r, ms));
let attempt = 0 ;
const flaky = async () => {
attempt++;
await wait (5 );
if (attempt < 3 ) throw new Error (`сбой ${attempt}` );
return "данные получены" ;
};
const alwaysBad = async () => { throw new Error ("навсегда" ); };
// async function retry(fn, times) { ... }
async function main () {
console.log (await retry (flaky, 5 ));
try {
await retry (alwaysBad, 2 );
} catch (err) {
console.log ("Не вышло:" , err.message);
}
}
main ();
Натиҷаи интизоршаванда Попытка 1
Попытка 2
Попытка 3
данные получены
Попытка 1
Попытка 2
Не вышло: навсегда
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 11.10 Ҳама якҷоя: load бо ҳолатҳо ва таймаут душвор
load(api, onChange)-ро нависед. Аввал onChange("loading"). Баъд дархост бо таймаути 100 мс (withTimeout-и омода). Натиҷа: массиви ғайрихолӣ — onChange("success:N"), холӣ — onChange("empty"), ҳар гуна хато (аз ҷумла таймаут) — onChange("error:" + паём). Истисноҳо ба берун намеафтанд.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((r) => setTimeout (r, ms));
const withTimeout = (promise, ms) => Promise.race ([
promise,
new Promise ((_, reject) => setTimeout (() => reject (new Error ("Таймаут" )), ms)),
]);
const apis = {
ok: async () => { await wait (10 ); return [1 , 2 , 3 ]; },
empty: async () => { await wait (10 ); return []; },
slow: async () => { await wait (300 ); return [1 ]; },
bad: async () => { await wait (10 ); throw new Error ("Сеть недоступна" ); },
};
// async function load(api, onChange) { ... }
async function main () {
for (const name of ["ok" , "empty" , "slow" , "bad" ]) {
const log = [];
await load (apis[name], (status) => log.push (status));
console.log (name + ": " + log.join (" > " ));
}
}
main ();
Натиҷаи интизоршаванда ok: loading > success:3
empty: loading > empty
slow: loading > error:Таймаут
bad: loading > error:Сеть недоступна
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
Пас аз озмоишӣ
Қайд кунед, кадом вазифаҳо нашуданд, ва ба ду савол ҷавоб диҳед: «кадом дарсро бояд аз нав хонам?» ва «агар дар кори назоратии ҳақиқӣ ЗС фаъол мебуд, чӣ мекардам — ва барои чӣ ин ба фаҳмидани мавзӯъ кумак намекард?». Таҳлили хатоҳои маъмулро муаллим дар охири машғулот мегузаронад. Дар вазифаи хонагӣ шумо вазифаҳои ҳалнашударо аз нав менависед.
12 Таҳлил: ЗС дар куҷо вақтро сарфа кард ва дар куҷо аз роҳ бурд
Ин блоки ЗС-и дарс аст: пас аз ду лоиҳа муҳим аст, ки на танҳо «ЗС-ро истифода баред», балки қимати ҳақиқии онро донед . Аксар вақт ба назар мерасад, ки ЗС корро тезонд, баъд шумо як соат хатоиро дар коди бегона ва нофаҳмо меҷустед. Баръакс низ мешавад: ЗС дар се дақиқа он чизро шарҳ дод, ки шумо як шом сарф мекардед. Барои фарқ кардани якдигар на эҳсосот, балки сабтҳо лозиманд.
Қоидаҳои курс, ки ҳоло месанҷем
№1: аввал 15 дақиқа худам, баъд ЗС. №2: кодеро, ки сатр ба сатр фаҳмонида наметавонӣ, намегузорем. №5: ЗС нусхаи пешакӣ менависад — ту мантиқ, номҳо ва ҳолатҳои канориро месанҷӣ. Таҳлил нишон медиҳад, ки ин қоидаҳоро дар куҷо риоя кардед ва дар куҷо не.
Монандӣ аз ҳаёт
Навигатор дар мошин. Дар шоҳроҳи ношинос дар вилояти Суғд ӯ соатҳоро сарфа мекунад. Аммо агар кӯркӯрона ба ҳар ҷое ки ӯ мегӯяд равед, метавонед ба роҳи баста расед. Ронандаи хуб медонад, ки ба куҷо рафтан мехоҳад, ва ишораҳоро бо аломатҳо муқоиса мекунад. ЗС низ навигатор аст: ҳадаф ва санҷиш бар дӯши шумо мемонад.
Таҳлили сохторнок: қолаб
3–5 эпизод -ро аз лоиҳа интихоб кунед, ки дар он ба ЗС муроҷиат кардед. Барои ҳар кадом як сатри ҷадвалро пур кунед. Мисол (варианти Б, обуҳаво):
Эпизод Чӣ пурсидам Чӣ гирифтам Натиҷа ± дақиқа Чӣ тавр санҷидам Нишонагузории кортаҳои обуҳаво «HTML ва CSS барои корта бисоз: шаҳр, ҳарорат, шамол» Нишонагузории корӣ, ду синфи зиёдатӣ ✅ сарфа кард +25 Дар браузер кушодам, зиёдатиро хориҷ кардам Дархост ба API «Маълумоти current-и open-meteo-ро чӣ тавр гирифтан мумкин?» URL-и дуруст, аммо бе санҷиши ok ⚖ қисман +15 / −10 Ҳангоми санҷиш бо хатои 404 ёфтам Коркарди хатоҳо «Тавре кун, ки наафтад» catch {}-и холӣ: хатоҳо хомӯшона фурӯ бурда мешуданд❌ аз роҳ бурд +5 / −40 Дар реҷаи Offline пай бурдам: экран тағйир намеёфт
Ва акнун — қолаб барои README-и шумо. Онро нусха бардоред ва бо эпизодҳои худатон пур кунед:
Қолаби таҳлил — ба README.md гузоред
## ИИ в проекте: где помог, где увёл в сторону
### Эпизод 1 : <что делал>
- Что просил (коротко): …
- Что получил: …
- Итог: ✅ сэкономил / ⚖ частично / ❌ увёл в сторону
- Минуты: сэкономил … / потерял …
- Как проверил результат: …
- Вывод для себя (правило): …
### Эпизод 2 : …
## Итог
- Где ИИ реально сэкономил время: …
- Где он увёл в сторону и почему я не заметил сразу: …
- Что я теперь делаю иначе: …
Се савол барои худсанҷӣ
Оё ман ин кодро сатр ба сатр шарҳ дода метавонам? Агар не — ин қарз аст: шумо чизи бегонаро гирифтед ва нафаҳмидед. Ё таҳлил кунед, ё аз нав бинависед.
Аз куҷо фаҳмидам, ки ҷавоби ЗС дуруст аст? «Кор кард» — санҷиши суст. Хуб: ба таври қасдӣ вайрон кардам (Offline, 404, дархости холӣ) ва боварӣ ҳосил намудам, ки рафтор бомаъност.
Бе ЗС чӣ мекардам — ва ин чӣ қадар арзиш дошт? Баҳои ростқавлона кумак мекунад, ки бифаҳмем, фоида дар куҷо воқеӣ аст ва дар куҷо — худфиребӣ.
«Аз роҳ бурданҳои» маъмул дар лоиҳаҳо бо API
ЗС чиро бад мекунад
response.ok-ро фаромӯш мекунад — 404 ҳамчун маълумот «бо муваффақият» нишон дода мешавад
catch-и холӣ ё танҳо console.log менависад ба ҷои паём ба корбар
Дар бораи рақобати ҷавобҳо ва дархости дукарата фикр намекунад
Майдонҳои вуҷуднадоштаи API-ро меандешад (data.weather.temp) — онҳоро бо ҷавоби ҳақиқӣ муқоиса кардан лозим аст
Зиёдатиро пешниҳод мекунад: китобхонаҳо, фреймворкҳо, чорчӯбаи мураккаби try/catch
ЗС дар куҷо воқеан кумак мекунад
Тақсими лоиҳа ба қадамҳо (қисми 04)
Шарҳи паёми нофаҳмои хато — бо коди шумо ва матни хато
Нусхаи пешакии нишонагузорӣ ва CSS, ки шумо баъд мехонед ва ислоҳ мекунед
Ревью аз рӯи чек-лист — пас аз одамон
README ва матнҳо — бо ислоҳи ҳатмӣ бо суханони худатон
кодамро баҳо деҳНусха бардоштан
Контекст: лоиҳаи таълимии «ҷустуҷӯи маҳсулот», JS + Vite, модулҳои api.js / ui.js / main.js. Медонам: fetch, async/await, try/catch, debounce.
Вазифа: ревьюи файли api.js-ро анҷом деҳ — танҳо мулоҳизаҳо, бе аз нав навиштани код.
Маҳдудиятҳо: ба 4 чиз нигоҳ кун: санҷиши response.ok, коркарди хатоҳо, номҳо, такрор.
Формати ҷавоб: рӯйхати «сатр → мушкил → чаро муҳим аст → чӣ тавр ислоҳро санҷидан».
Санҷиш: дар охир як ҷойро номбар кун, ки боварӣ надорӣ, ки ман API-ро дуруст фаҳмидам.
[коди api.js-ро гузоред]Нусха бардоштан
Муфассалтар хонед: MDN — ислоҳи хатои JavaScript
Амал: қимати ЗС-ро ҳисоб мекунем
ВАЗИФАИ 12.1 Хулосаҳои таҳлили эпизодҳо миёна
Эпизодҳои таҳлил дар массив ҳастанд. Барои ҳар кадом нишон дода шудааст, ки ЗС чанд дақиқа сарфа кард (saved) ва чанд дақиқа гум кард (lost: ҷустуҷӯи хато дар коди бегона, аз нав навиштан). Маҷмӯъҳо ва натиҷаи бо аломатро (+20 ё -5) ҳисоб кунед ва эпизоди бо зиёнии калонтаринро ёбед. Чор сатрро аз рӯи намунаи зер чоп кунед.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const episodes = [
{ task: "разметка карточек" , saved: 25 , lost: 0 },
{ task: "запрос к API" , saved: 15 , lost: 10 },
{ task: "debounce" , saved: 10 , lost: 0 },
{ task: "обработка ошибок" , saved: 5 , lost: 40 },
{ task: "README" , saved: 15 , lost: 0 },
];
// ҳисоб кунед ва чор сатрро чоп намоед
Натиҷаи интизоршаванда Сэкономил: 70 мин
Потерял: 50 мин
Итого: +20 мин
Главная ловушка: обработка ошибок
Ишора 1 Ду маҷмӯъро ду reduce (ё як давра) ҷамъ мекунад. Натиҷа — фарқи saved − lost.
Ишора 2 Аломат: net > 0 ? "+" + net : String(net). Эпизоди бадтарин — reduce, ки унсурро бо lost-и калонтар мемонад.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
13 Вазифаи хонагӣ
Лоиҳаро аз рӯи мулоҳизаҳои ревью ва ҳимоя такмил диҳед, таҳлили «ЗС дар лоиҳа»-ро ороиш диҳед ва оид ба кори назоратӣ кор бар хатоҳо кунед.
Чӣ кор кардан лозим
☐ Мулоҳизаҳои ревью ва ҳимояро, ки қабул кардед, ислоҳ кунед.
☐ Ҳамаи бандҳои MVP-ро аз қисми 02 санҷед ва чек-листи ревьюерро аз рӯи лоиҳаи худ боз як бор гузаред; npm run build бе хато.
☐ console.log-ҳои зиёдатӣ, коди шарҳшуда ва функсияҳои мурдаро хориҷ кунед.
☐ Ба README бахши «ЗС дар лоиҳа»-ро аз рӯи қолаби қисми 12 илова кунед (3–5 эпизод ва хулоса — бо суханони худатон).
☐ Репозиторийро навсозӣ кунед: оммавӣ, README бо скриншот, на камтар аз 5 commit-и бомаъно, node_modules ва dist бор нашудаанд.
☐ Кор бар хатоҳо: ҳар вазифаи кори назоратии озмоиширо, ки ҳал накардед ё бо хато ҳал кардед, аз нав ҳал кунед ва бо суханони худатон шарҳ диҳед , ки хато дар чӣ буд (1–2 ҷумла дар шарҳ).
Чӣ супоридан лозим
Истиноди репозиторийро ба чати гурӯҳ (Telegram) фиристед. Дар паём нависед: варианти лоиҳа (А, Б ё В), кадом API-ро истифода кардед, пас аз ревью чӣ илова кардед, кадом бонус сохтед, ва рӯйхати вазифаҳои кори назоратӣ, ки аз нав кардед.
Вазифаи хонагӣ чӣ тавр баҳо дода мешавад (0–10)
Чиро месанҷем Холҳо Истинод бе вуруд кушода мешавад, npm run build дар нусхаи тоза мегузарад 2 Мулоҳизаҳои ревью ислоҳ шудаанд (дар commit-ҳо намоён аст) 2 README: тавсиф, скриншот ва бахши «ЗС дар лоиҳа» бо суханони худатон 3 На камтар аз 5 commit-и бомаъно бо паёмҳои фаҳмо 1 Кор бар хатоҳо оид ба кори назоратӣ бо шарҳҳо 2
Ин баҳо барои вазифаи хонагии дарс аст (0–10). Баҳо барои лоиҳаи хурд (0–100) аз рӯи ҷадвали қисми 03 гузошта мешавад ва алоҳида ҳисоб карда мешавад.
✓ Варақаи кӯмакии дарс
Лоиҳа: барнома дар API-и оммавӣ (маҳсулот, обуҳаво ё корбарон) дар Vite. Баҳо 0–100: MVP 20, fetch ва async/await 20, ҳолатҳо 15, debounce ва назорати дархостҳо 10, модулҳо 10, ҷамъбаст ва репозиторий 5, интерфейс 5, ҳимоя 15; бонус то +5.
fetch: await fetch(url) → if (!response.ok) throw … → await response.json(). fetch танҳо ҳангоми нокомии шабака меафтад, 404 ва 500 — ҷавобҳои «муваффақ».
Ҳолатҳо: як объекти { status, items, error }, status: idle / loading / success / error; success-и холӣ — ин empty аст. Иваз шудани статус майдонҳои зиёдатиро тоза мекунад.
try/catch/finally: catch ба корбар паёми фаҳмо нишон медиҳад, на хомӯш мемонад; finally ҳамеша иҷро мешавад.
Мувозӣ ё пай дар пай: дархостҳои мустақил — Promise.all, вобастаҳо — await пай дар пай. Promise.race — барои таймаут.
debounce: таймерро ҳангоми ҳар даъват аз сифр мекунем; пас аз таваққуф кор мекунад. Дархости холиро ба сервер намефиристем.
Рақобати ҷавобҳо: рақами дархост (myId !== latestId → нодида) ё AbortController.
Модулҳо: api.js — шабака, ui.js — DOM, main.js — пайвандак; пеш аз ҳимоя npm run build + preview; dist ва node_modules дар Git нестанд.
Ревью: иҷро (Offline, Slow 3G, партов) → хондан аз рӯи чек-лист → мулоҳиза = дар куҷо, чӣ мебинам, чаро, пешниҳод.
Кори назоратии №2: 30 дақиқа, бе ЗС, мавзӯъҳо — объектҳо, async/await, fetch, хатоҳо; 10 вазифа бо санҷиши худкор.
ЗС дар лоиҳа: эпизодҳоро сабт кунед (чӣ пурсидам → чӣ гирифтам → натиҷа → ± дақиқа → чӣ тавр санҷидам). ЗС аксар вақт ok-ро фаромӯш мекунад, хатоҳоро фурӯ мебарад ва майдонҳои API-ро меандешад — санҷиш бар дӯши шумо мемонад.