Дарси 13 · Async ва API
JavaScript-и ғайрисинхронӣ
Вақте шумо сайтро мекушоед, он то боршавии расмҳо, қурби асъор ё рӯйхати мол ях намебандад. Саҳифа зинда аст, маълумот бошад баъдтар «меояд». Ин ғайрисинхронӣ (асинхронӣ) аст: JavaScript одат кардааст, ки назди оташ интизор нашавад, балки то омодашавии ҷавоб бо корҳои дигар машғул шавад. Имрӯз мефаҳмем, ин чӣ тавр кор мекунад ва навиштани чунин кодро бе саргардонӣ меомӯзем.
Фарқи байни коди синхронӣ ва ғайрисинхрониро шарҳ додан
Амалҳоро бо setTimeout ба таъхир гузоштан ва бо setInterval такрор кардан
Кодро бо колбэкҳо хондан ва фаҳмидани он, ки «дӯзахи колбэкҳо» чаро бад аст
Промисҳо сохтан ва занҷираҳои then / catch / finally бастан
async / await-ро бо try / catch навиштан
Тартиби чопро пешгӯӣ кардан: стек, микровазифаҳо, макровазифаҳо (event loop)
Бо ин саҳифа чӣ тавр кор кардан лозим
Тамоми коди дар заминаи торик бо тугмаи ▶ Иҷро кардан зинда аст. Онро тағйир додан ва натиҷаро дарҳол дар консол дидан мумкин аст. Дар ин дарс код аксар вақт чизеро бо таъхир чоп мекунад — як сония интизор шавед, то консол сатрҳоро пурра кунад. Вазифаҳои «тартиби чопро пешгӯӣ кун» бисёранд: аввал фикр кунед ва пешгӯии худро нависед, баъд иҷро кунед. Ишораҳо зери қулфак 🔒 пинҳонанд — танҳо вақте кушоед, ки монда бошед.
01 Синхронӣ ва ғайрисинхронӣ. setTimeout
То имрӯз тамоми коди мо синхронӣ буд: JavaScript сатрҳоро қатъиян бо тартиб, яке пас аз дигаре иҷро мекард ва сатри оянда то анҷоми сатри қаблӣ оғоз намешуд.
Коди синхронӣ: қатъиян аз боло ба поён · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
console.log ("1. Открыли приложение" );
console.log ("2. Посчитали сумму" );
console.log ("3. Показали результат" );
Аммо дар барномаҳои воқеӣ корҳое ҳастанд, ки вақт мегиранд : дархост ба сервер, боркунии расм, таймер, ҷавоби корбар. Агар ҳар якеро то анҷомаш интизор шавем, саҳифа «ях мебандад». Барои ҳамин чунин корҳоро оғоз мекунанд ва интизор намешаванд : вақте натиҷа омода шавад, JavaScript ба он бармегардад. Ин аст коди ғайрисинхронӣ .
Қиёс аз ҳаёт
Шумо ба чойхона омада, палав фармоиш додед. Пешхизмат то пухтани биринҷ назди дег намеистад — ӯ аз дигар мизҳо фармоиш мегирад. Вақте палав тайёр шавад, ошпаз пешхизматро садо медиҳад ва ӯ хӯрокро ба назди шумо меорад. Пешхизмати синхронӣ 40 дақиқа назди дег меистод ва ба ҳеҷ кас хизмат намекард. Ғайрисинхронӣ бошад — пухтанро оғоз кард ва рафт.
setTimeout — «инро баъдтар иҷро кун»
Роҳи осонтарини ба даст овардани ғайрисинхронӣ — функсияи setTimeout(функсия, миллисония). Вай ба браузер мегӯяд: «баъди ин қадар миллисония ин функсияро даъват кун» ва худаш фавран бармегардад. 1000 мс = 1 сония.
Кодҳои баъд аз setTimeout интизор намешаванд · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
console.log ("Заказали плов" );
setTimeout (() => {
console.log ("Плов готов!" );
}, 500 );
console.log ("Официант идёт к другому столу" );
Ба тартиб диққат диҳед: «Официант идёт…» пештар аз «Плов готов!» пайдо шуд, ҳарчанд поёнтар навишта шудааст. Функсияи дохили setTimeout-ро мо месупорем , даъват намекунем: вай баъдтар кор мекунад. Чунин функсия колбэк (callback — «баргашта занг зан») номида мешавад — дар бораи он дар қисми оянда муфассалтар.
Таъхири сифр ҳам ғайрисинхронӣ аст
Ҳайратомезтарин ҳолат: ҳатто setTimeout(…, 0) функсияро фавран иҷро намекунад. Вай онро ба навбат мегузорад — «баъд аз он ки тамоми коди ҷорӣ анҷом ёбад».
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
console.log ("A" );
setTimeout (() => console.log ("B (с нулевой задержкой)" ), 0 );
console.log ("C" );
A — сатри оддӣ, фавран чоп мешавад.
setTimeout — функсия «ба як сў гузошта шуд». JavaScript минбаъд бе ақиб нигоҳ кардан мегузарад.
C — фавран чоп мешавад.
Тамоми код анҷом ёфт ва танҳо акнун JavaScript функсияи ба таъхир гузоштаро мебарорад ва B-ро чоп мекунад.
Аргументҳо ва бекор кардан
setTimeout рақам бармегардонад — рақами таймер. Бо ёрии он таймерро то кор карданаш тавассути clearTimeout бекор кардан мумкин аст.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const timerId = setTimeout (() => console.log ("Это не выведется" ), 300 );
console.log ("Таймер запущен, номер есть:" , typeof timerId);
clearTimeout (timerId);
console.log ("Таймер отменили" );
setInterval — «ҳар N мс такрор кун»
setInterval ҳамин тавр кор мекунад, аммо функсияро борҳо ва борҳо даъват мекунад, то он даме ки онро тавассути clearInterval қатъ кунед. Агар қатъ карданро фаромӯш кунед — таймер то абад тик-так мекунад (дар ин саҳифа иҷро баъди 8 сония қатъ мешавад).
Ҳисоби баръакс · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
let left = 3 ;
const id = setInterval (() => {
console.log ("Осталось:" , left);
left--;
if (left === 0 ) {
clearInterval (id); // қатъ мекунем, вагарна то абад тик-так мекунад
console.log ("Поехали!" );
}
}, 200 );
Хатои маъмул
Функсияро ба ҷои супоридан даъват кардан. setTimeout(sayHi(), 1000) — қавсҳо функсияро ҳамин лаҳза иҷро мекунанд , ба таймер бошад, он чи вай баргардонд (яъне ҳеҷ чиз) меравад. Бояд setTimeout(sayHi, 1000) ё setTimeout(() => sayHi(), 1000) навишт.
Хато: таймер фавран кор кард · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
function sayHi () {
console.log ("Салом!" );
}
setTimeout (sayHi (), 1000 ); // ✖ «Салом!» якбора чоп мешавад, на баъди як сония
console.log ("Конец кода" );
Муфассалтар хонед: learn.javascript.ru — setTimeout ва setInterval · MDN — setTimeout
Амал: мустаҳкам мекунем
Аксари вазифаҳои ин дарс дар бораи тартибест , ки сатрҳо ба консол мерасанд. Дар вазифаҳои «тартибро пешгӯӣ кун» код худаш пешгӯии шуморо бо воқеият муқоиса мекунад: ҷавобро ба массиви prediction ворид кунед ва иҷро намоед. Агар «Верно!»-ро бинед — шумо мисли JavaScript фикр мекунед.
ВАЗИФАИ 1.1 Фармоиш дар чойхона осон
Палав фармоиш диҳед: байни ду сатр таймере илова кунед, ки баъд аз 500 мс «Плов готов!»-ро чоп кунад. Пешхизмат набояд интизор шавад — сатр дар бораи мизи дигар бояд пештар пайдо шавад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
console.log ("Заказ принят" );
// инҷо таймерро барои 500 мс оғоз кунед
console.log ("Официант идёт к другому столу" );
Натиҷаи интизоршаванда Заказ принят
Официант идёт к другому столу
Плов готов!
Ишора 1 setTimeout бо ду аргумент лозим аст: функсия ва шумораи миллисонияҳо.
Ишора 2 setTimeout(() => { console.log("Плов готов!"); }, 500); — ва бигзор сатр байни ду console.log бошад.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 1.2 Тартибро пешгӯӣ кун: се таймер осон
Функсияи log нишонаҳоро бо тартиби чоп ба хотир мегирад. Бе иҷро кардани код тартиби нишонаҳоро, ки пайдо мешаванд, ба prediction ворид кунед (масалан, ["1", "2", "3", "4"]). Сипас иҷро кунед — санҷиш дар охир мегӯяд, ки шумо дуруст пешгӯӣ кардед ё не.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const actual = [];
const log = (label) => actual.push (label);
log ("1" );
setTimeout (() => log ("2" ), 100 );
setTimeout (() => log ("3" ), 50 );
log ("4" );
const prediction = []; // пешгӯии шумо: тартиби нишонаҳо
// --- санҷиш, тағйир надиҳед ---
setTimeout (() => console.log (actual.join (" " ) === prediction.join (" " ) ? "Верно!" : "Не угадали, подумайте ещё" ), 400 );
Натиҷаи интизоршаванда Верно!
Ишора 1 Аввал тамоми коди синхронӣ иҷро мешавад — инҳо нишонаҳои 1 ва 4 мебошанд. Таймерҳо интизор мешаванд.
Ишора 2 Аз таймерҳо он пештар кор мекунад, ки таъхираш камтар аст: 50 мс пештар аз 100 мс — новобаста аз тартиби навишт дар код.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 1.3 Оғози мусобиқа миёна
Ҳисоби баръакс созед: ҳар 100 мс аз 3 сар карда рақам чоп кунед. Вақте рақам ба 0 расад, «Старт!»-ро (ба ҷои нул) чоп кунед ва таймерро қатъ намоед.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
let n = 3 ;
// setInterval-ро барои 100 мс оғоз кунед
Натиҷаи интизоршаванда 3
2
1
Старт!
Ишора 1 Рақами таймерро нигоҳ доред: const id = setInterval(…) — вай барои clearInterval(id) лозим мешавад.
Ишора 2 Дар дохили колбэк: агар n === 0 бошад — «Старт!»-ро чоп кунед, таймерро қатъ намоед ва return нависед. Вагарна n-ро чоп кунед ва онро 1 кам намоед.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 1.4 Хаторо ёб: таймер интизор намешавад миёна
Паём «Таймер сработал» бояд баъд аз «Конец», баъди 200 мс пайдо шавад. Ҳоло вай фавран пайдо мешавад. Хаторо ёбед ва ислоҳ кунед.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
console.log ("Начало" );
setTimeout (console.log ("Таймер сработал" ), 200 );
console.log ("Конец" );
Натиҷаи интизоршаванда Начало
Конец
Таймер сработал
Ишора 1 Қавсҳои console.log(...) функсияро фавран даъват мекунанд. Ба setTimeout бояд функсия дод, на натиҷаи даъвати он.
Ишора 2 Даъватро ба функсияи тирдор печонед: () => console.log("Таймер сработал").
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
02 Callback: «вақте омода шуд, занг зан»
Мо аллакай функсияҳоро ба map ва filter додаем. Функсияе, ки ба функсияи дигар «барои баъд» дода мешавад, колбэк номида мешавад. Пештар колбэкҳо фавран, дар дохили давра даъват мешуданд. Дар коди ғайрисинхронӣ бошад колбэк вақте кор анҷом ёбад даъват мешавад.
Функсия дар бораи натиҷа тавассути колбэк хабар медиҳад · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
function loadPrice (dish, callback) {
console.log ("Спрашиваем цену:" , dish);
setTimeout (() => {
const price = dish === "плов" ? 35 : 10 ;
callback (price); // бо натиҷа «занг мезанем»
}, 300 );
}
loadPrice ("плов" , (price) => {
console.log ("Цена плова:" , price, "сомони" );
});
console.log ("Пока ждём ответ, можно заняться другими делами" );
Қиёс аз ҳаёт
Шумо дар қаннодӣ торт фармоиш дода, рақами худро мегузоред: «Вақте тайёр шуд, занг занед». Рақам — ин колбэк аст. Шумо ба корҳоятон меравед, қаннод бошад худаш занг мезанад. Шуморо лозим нест назди витрина истода, ҳар панҷ дақиқа пурсед.
Колбэк бо хато: шартномаи «error-first»
Кори ғайрисинхронӣ метавонад муваффақ нашавад: шабака нест, чунин мол нест, парол нодуруст аст. Барои ҳамин аз рӯи анъана колбэк аввалин аргументро хато (ё null, агар ҳама чиз хуб бошад), дуюмро — натиҷа мегирад.
Колбэк (error, result) · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
function findStudent (id, callback) {
setTimeout (() => {
if (id !== 1 ) {
callback (new Error ("студент не найден" )); // хато — аргументи аввал
return ;
}
callback (null , "Мадина" ); // муваффақият — хато нест
}, 200 );
}
findStudent (1 , (error, name) => {
if (error) {
console.log ("Ошибка:" , error.message);
return ;
}
console.log ("Нашли:" , name);
});
findStudent (7 , (error, name) => {
if (error) {
console.log ("Ошибка:" , error.message);
return ;
}
console.log ("Нашли:" , name);
});
Дӯзахи колбэкҳо (callback hell)
Агар қадамҳо аз ҳам вобаста бошанд чӣ? Аввал корбарро ёфтан, баъд фармоишҳои ӯро, баъд суроғаи расониданро. Ҳар қадами оянда бояд ба колбэки қаблӣ дохил карда шавад. «Нардбон» ҳосил мешавад, ки ба тарафи рост мегурезад.
Пирамидаи тақдир · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
function step (name, callback) {
setTimeout (() => {
console.log ("Готово:" , name);
callback ();
}, 100 );
}
step ("нашли пользователя" , () => {
step ("загрузили заказы" , () => {
step ("узнали адрес" , () => {
step ("посчитали доставку" , () => {
console.log ("Всё готово!" );
});
});
});
});
Ҳамагӣ чор қадам, аммо код аллакай душвор хонда мешавад. Агар дар ҳар сатҳ коркарди хаторо илова кунем — лабиринти ҳақиқӣ ҳосил мешавад. Маҳз ҳамин мушкилотро промисҳо ҳал карданд, ки дар бораи онҳо андаке баъдтар сӯҳбат мекунем: ҳамин қадамҳо дар як занҷири ҳамвор саф мекашанд.
Колбэкҳо Дохилшавӣ ба тарафи рост меафзояд. Хатоҳоро дар ҳар сатҳ бояд дастӣ санҷид. Кодро тағйир додан душвор аст.
Промисҳо ва async/await Қадамҳо яке пас аз дигаре дар як сутуни ҳамвор мераванд. Хатоҳоро як ҷой дастгир мекунад — catch ё try/catch.
Хатои маъмул
Баъд аз даъвати ғайрисинхронӣ код навиштан ва интизор шудан, ки натиҷа аллакай ҳаст. Колбэк ҳанӯз кор накардааст, сатри поён бошад аллакай иҷро шуд.
Хато: натиҷа ҳанӯз нест · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
let price;
setTimeout (() => {
price = 35 ;
}, 200 );
console.log ("Цена плова:" , price); // ✖ undefined — таймер ҳанӯз кор накардааст
Ҳар чизе, ки аз натиҷа вобаста аст, бояд дар дохили колбэк (ё, чунон ки минбаъд мебинем, баъд аз await) иҷро шавад.
Муфассалтар хонед: learn.javascript.ru — Муқаддима: колбэкҳо · MDN — Callback function
Амал: мустаҳкам мекунем
Функсияҳои ғайрисинхронии худамонро бо колбэкҳо менависем ва хатоҳоро коркард мекунем.
ВАЗИФАИ 2.1 Меню бо таъхир осон
Функсияи loadMenu(callback)-ро нависед: баъд аз 200 мс вай callback-ро даъват мекунад ва массиви ["самбуса", "курутоб", "чой"]-ро ба он мемонад. Даъвати функсия аллакай навишта шудааст.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
// function loadMenu(callback) { ... }
loadMenu ((menu) => {
console.log ("Меню загружено, блюд:" , menu.length);
console.log (menu.join (", " ));
});
Натиҷаи интизоршаванда Меню загружено, блюд: 3
самбуса, курутоб, чой
Ишора 1 Дар дохили функсия setTimeout барои 200 мс лозим аст. Колбэк дар дохили таймер даъват мешавад.
Ишора 2 setTimeout(() => callback(["самбуса", "курутоб", "чой"]), 200);
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 2.2 Санҷиши синну сол миёна
Функсияи checkAge омода аст ва натиҷаро аз рӯи қоидаи error-first хабар медиҳад. Онро ду маротиба даъват кунед — барои синни 20 ва барои 15 — ва дар колбэк ё паёми муваффақият, ё Ошибка: …-ро бо матни хато чоп кунед.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
function checkAge (age, callback) {
setTimeout (() => {
if (age < 18 ) {
callback (new Error ("слишком мал" ));
} else {
callback (null , "Добро пожаловать!" );
}
}, 100 );
}
// checkAge(20, …) ва checkAge(15, …)-ро даъват кунед
Натиҷаи интизоршаванда Добро пожаловать!
Ошибка: слишком мал
Ишора 1 Колбэк ду параметр мегирад: (error, result). Аввал error-ро месанҷем.
Ишора 2 (error, result) => { if (error) { console.log("Ошибка: " + error.message); return; } console.log(result); } — ин колбэкро дар ҳарду даъват истифода бурдан мумкин аст.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 2.3 Фармоиши палав қадам ба қадам осон
Се қадами фармоиш аллакай навишта шудаанд, ҳар кадом 100 мс мегирад. Онҳоро яке аз паси дигаре оғоз кунед: қадами оянда дар колбэки қаблӣ даъват мешавад. Ҳар қадам сатреро ба колбэк мемонад — онро чоп кунед.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
function takeOrder (callback) { setTimeout (() => callback ("заказ принят" ), 100 ); }
function cook (callback) { setTimeout (() => callback ("плов приготовлен" ), 100 ); }
function serve (callback) { setTimeout (() => callback ("плов на столе" ), 100 ); }
// занҷирро созед: takeOrder → cook → serve
Натиҷаи интизоршаванда заказ принят
плов приготовлен
плов на столе
Ишора 1 Аз takeOrder((text) => { ... }) оғоз кунед. Дар дохили колбэк text-ро чоп кунед ва қадами оянда-ро даъват намоед.
Ишора 2 Се сатҳи дохилшавӣ ҳосил мешавад: takeOrder(…) дар худ cook(…)-ро дорад, ва он дар худ serve(…)-ро. Ин ҳамон «пирамидаи» хурд аст.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
03 Чӣ тавр кор мекунад: event loop
JavaScript якрешагӣ аст: вай як даст дорад ва дар як вақт як кор мекунад. Пас таймерҳо ва дархостҳо чӣ тавр «худ аз худ мераванд»? Онҳоро JavaScript не, балки браузер интизор мешавад. Вақте таймер кор кард, браузер колбэки шуморо ба навбат мегузорад, механизми махсус — event loop (давраи ҳодисаҳо) — бошад онро аз он ҷо мебарорад, вақте ки JavaScript озод шавад.
Қиёс аз ҳаёт
Як дастгоҳи касса дар мағозаи Шоҳмансурро тасаввур кунед. Кассир (стеки даъватҳо) дар як вақт як харидорро хизмат мекунад. Боқӣ дар навбатҳо меистанд. Аммо навбат дутост: дар «кассаи тез» онҳое меистанд, ки як харид доранд (микровазифаҳо — промисҳо), дар навбати оддӣ — боқӣ ҳама (макровазифаҳо — таймерҳо). Кассир бо харидор тамом кард ва аввал тамоми кассаи тезро хизмат мекунад ва танҳо баъд аз навбати оддӣ як нафарро мегирад.
Схема
Call Stack Стеки даъватҳо: чӣ ҳоло иҷро мешавад main()console.log()
Web API (браузер) Инҷо таймерҳо ва дархостҳо «интизор мешаванд». JavaScript банд нест setTimeoutfetchкликҳо
Навбати микровазифаҳо Кассаи тез: аввал мераванд promise.thenawaitqueueMicrotask
Навбати макровазифаҳо Навбати оддӣ: дар як давр яктоӣ колбэки setTimeoutsetIntervalҳодисаҳо
Event loop: стек холӣ → ҲАМАИ микровазифаҳоро иҷро кун → ЯК макровазифаро бигир → боз аз сар
Аввал тамоми коди синхронӣ, баъд микровазифаҳо, баъд яктоӣ макровазифаҳо
Call Stack Стеки даъватҳо. Дар ин ҷо JavaScript кор мекунад. То даме ки дар стек код ҳаст, боқӣ ҳама интизоранд.
Макровазифа Колбэки таймери setTimeout / setInterval, коркарди клик ва монанди инҳо. Дар як «давр» танҳо яктояш иҷро мешавад.
Микровазифа Колбэкҳои .then / .catch / .finally, идомаи баъд аз await, queueMicrotask. Баъд аз ҳар макровазифа ҳама иҷро мешаванд, то навбат холӣ шавад.
Таҳлил қадам ба қадам
Классикаи мусоҳибаҳо · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
console.log ("1" );
setTimeout (() => console.log ("2" ), 0 );
Promise.resolve ().then (() => console.log ("3" ));
console.log ("4" );
Коди синхронӣ. Ба стек console.log("1") меафтад — 1 чоп мешавад.
setTimeout. Таймер ба браузер супорида шуд. Баъд аз 0 мс колбэки он ба навбати макровазифаҳо мегузарад. Вай ҳоло иҷро намешавад.
Promise.resolve().then(…). Промис аллакай иҷро шудааст, барои ҳамин колбэки then фавран ба навбати микровазифаҳо мегузарад.
Коди синхронӣ. console.log("4") — 4 чоп мешавад. Стек холӣ шуд.
Микровазифаҳо. Event loop мебинад, ки навбати микровазифаҳо холӣ нест ва колбэкро иҷро мекунад — 3 чоп мешавад.
Макровазифа. Акнун навбати микровазифаҳо холӣ аст ва як макровазифаро гирифтан мумкин аст — колбэки таймер: 2 чоп мешавад.
Натиҷа: 1, 4, 3, 2 . Қоидаро дар хотир доред: коди синхронӣ → микровазифаҳо (промисҳо) → макровазифаҳо (таймерҳо) .
Микровазифаҳо баъд аз ҳар макровазифа медароянд
Агар дар макровазифа промис сохта шавад, колбэки он фавран баъд аз вай , ҳанӯз пеш аз макровазифаи навбатӣ аз навбат иҷро мешавад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
setTimeout (() => {
console.log ("таймер 1" );
Promise.resolve ().then (() => console.log ("промис внутри таймера 1" ));
}, 0 );
setTimeout (() => console.log ("таймер 2" ), 0 );
Тартиб: таймери 1 , промиси дохили таймери 1 , таймери 2 . Микровазифае, ки таймери 1 таваллуд кард, пештар аз он расид, ки «навбати оддӣ» ба таймери 2 бирасад.
Хатои маъмул
Гумон кардан, ки setTimeout(fn, 0) «фавран» кор мекунад. Дар асл вай танҳо вақте кор мекунад, ки тамоми коди ҷорӣ ва ҳамаи микровазифаҳо анҷом ёбанд . Агар коди ҷорӣ бо давраи вазнин банд бошад, таймер интизор мешавад, то давра анҷом ёбад: setTimeout «на пештар аз N мс» кафолат медиҳад, на «дақиқан баъди N мс».
Маслиҳат: тартибро чӣ тавр пешгӯӣ кардан
Кодро аз боло ба поён бингаред ва сатрҳоро ба се «сабад» тақсим кунед: 1. фавран иҷро мешавад , 2. ба микровазифаҳо (then, await), 3. ба макровазифаҳо (setTimeout; таъхираш камтар — пештар). Баъд бихонед: сабади 1 → сабади 2 → сабади 3. Агар дар дохили колбэк сабади нави 2 ё 3 пайдо шавад, ҳамин корро такрор кунед.
Муфассалтар хонед: learn.javascript.ru — Давраи ҳодисаҳо · learn.javascript.ru — Микровазифаҳо · MDN — Event loop
Амал: тартиби чопро пешгӯӣ кун
Ин машқи асосии дарс аст. Барои ҳар вазифа аввал сатрҳоро дар коғаз ба сабадҳо тақсим кунед, ҷавобро ба prediction ворид намоед ва танҳо баъд иҷро кунед.
Тартиби нишонаҳоро ворид кунед.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const actual = [];
const log = (label) => actual.push (label);
log ("A" );
setTimeout (() => log ("B" ), 0 );
log ("C" );
const prediction = []; // масалан: ["A", "B", "C"]
// --- санҷиш, тағйир надиҳед ---
setTimeout (() => console.log (actual.join (" " ) === prediction.join (" " ) ? "Верно!" : "Не угадали, подумайте ещё" ), 400 );
Натиҷаи интизоршаванда Верно!
Ишора 1 Таймер, ҳатто нулӣ, ба навбати макровазифаҳо меравад — баъд аз тамоми коди синхронӣ.
Ишора 2 log("A") ва log("C") ба таври синхронӣ иҷро мешаванд. Баъд — таймер бо нишонаи B.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 3.2 Промис дар муқобили таймер миёна
Кӣ тезтар аст: промис ё таймер бо таъхири сифр?
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const actual = [];
const log = (label) => actual.push (label);
log ("1" );
setTimeout (() => log ("2" ), 0 );
Promise.resolve ().then (() => log ("3" ));
log ("4" );
const prediction = [];
// --- санҷиш, тағйир надиҳед ---
setTimeout (() => console.log (actual.join (" " ) === prediction.join (" " ) ? "Верно!" : "Не угадали, подумайте ещё" ), 400 );
Натиҷаи интизоршаванда Верно!
Ишора 1 Ин ҳамон мисолест, ки дар боло таҳлил кардем, танҳо нишонаҳо бо рақамҳо иваз шудаанд. Аммо кӯшиш кунед, ки худатон ҳал кунед, бе назар кардан.
Ишора 2 Тартиби сабадҳо: фавран (1, 4) → микровазифаҳо (3) → макровазифаҳо (2).
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 3.3 Ду микровазифа осон
Дар ин ҷо ду роҳи сохтани микровазифа ҳаст: queueMicrotask ва then. Онҳо дар як навбат меистанд — бо тартиби илова шудан.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const actual = [];
const log = (label) => actual.push (label);
setTimeout (() => log ("таймер" ), 0 );
queueMicrotask (() => log ("микро-1" ));
Promise.resolve ().then (() => log ("микро-2" ));
log ("синхронно" );
const prediction = []; // чор нишона: синхронӣ, ду микро ва таймер
// --- санҷиш, тағйир надиҳед ---
setTimeout (() => console.log (actual.join (" " ) === prediction.join (" " ) ? "Верно!" : "Не угадали, подумайте ещё" ), 400 );
Натиҷаи интизоршаванда Верно!
Ишора 1 Таймер ҳамеша дар охири охир аст, сатри синхронӣ бошад — дар аввали аввал.
Ишора 2 Байни онҳо микровазифаҳо бо ҳамон тартибе, ки ба навбат илова шуданд : аввал queueMicrotask, баъд then.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 3.4 Навбатҳои дарунӣ душвор
Вазифаи андаке душвортар: колбэкҳо худашон таймерҳо ва промисҳои нав месозанд. Қоидаро дар хотир доред: баъд аз ҳар макровазифа ҳамаи микровазифаҳои ҷамъшуда иҷро мешаванд.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const actual = [];
const log = (label) => actual.push (label);
setTimeout (() => {
log ("A" );
Promise.resolve ().then (() => log ("B" ));
}, 0 );
setTimeout (() => log ("C" ), 0 );
Promise.resolve ().then (() => {
log ("D" );
setTimeout (() => log ("E" ), 0 );
});
log ("F" );
const prediction = [];
// --- санҷиш, тағйир надиҳед ---
setTimeout (() => console.log (actual.join (" " ) === prediction.join (" " ) ? "Верно!" : "Не угадали, подумайте ещё" ), 400 );
Натиҷаи интизоршаванда Верно!
Ишора 1 Аввал F (синхронӣ), баъд микровазифаи ягона D. Вай ба навбати макровазифаҳо боз як таймер — E-ро дар охири навбат, баъд аз A ва C мегузорад.
Ишора 2 Навбати макровазифаҳо баъд аз давраи аввал: A, C, E. Аммо баъд аз иҷрои A микровазифаи он B фавран кор мекунад — пештар аз C.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 3.5 Таъхирҳо ва занҷир душвор
Таймерҳо бо таъхирҳои гуногун ва занҷири аз ду then. Занҷир — ин ду микровазифаи пай дар пай аст: дуюмаш вақте пайдо мешавад, ки аввалӣ иҷро шуд, аммо ба ҳар ҳол пештар аз ҳар гуна таймер.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const actual = [];
const log = (label) => actual.push (label);
setTimeout (() => log ("T200" ), 200 );
setTimeout (() => log ("T0" ), 0 );
Promise.resolve ().then (() => log ("P1" )).then (() => log ("P2" ));
setTimeout (() => log ("T100" ), 100 );
log ("S" );
const prediction = [];
// --- санҷиш, тағйир надиҳед ---
setTimeout (() => console.log (actual.join (" " ) === prediction.join (" " ) ? "Верно!" : "Не угадали, подумайте ещё" ), 400 );
Натиҷаи интизоршаванда Верно!
Ишора 1 Ба таври синхронӣ — танҳо S. Баъд ҳамаи микровазифаҳо: P1 ва аз паси он P2.
Ишора 2 Таймерҳо аз рӯи афзудани таъхир кор мекунанд: 0, 100, 200 — новобаста аз он ки дар код бо кадом тартиб навишта шудаанд.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
04 Promise: ваъдаи натиҷа
Промис (Promise — «ваъда») — ин объектест, ки натиҷаи кори ғайрисинхрониро ифода мекунад, ки ҳоло нест, вале хоҳад буд : ё қимат, ё хато. Ба ҷои колбэкҳои дохилшуда мо объекте мегирем, ки ба он бо усулҳои then ва catch «обуна шудан» мумкин аст.
Қиёс аз ҳаёт
Шумо расониданро пардохт кардед ва чек бо рақами фармоиш гирифтед. Ин ҳоло мол нест, балки ваъда аст: «мол хоҳад омад». Ваъда се ҳолат дорад: интизорӣ (фармоиш дар роҳ), иҷрошуда (курйер овард) ё радшуда (мол дар анбор нест). Чекро шумо фавран дар даст доред, мол баъдтар меояд — ё бекор мешавад.
Се ҳолати промис
pending «Интизор аст». Ҳолати ибтидоӣ: натиҷа ҳанӯз нест.
fulfilled «Иҷро шуд». Кор бомуваффақият анҷом ёфт, промис қимат дорад. Колбэки then даъват мешавад.
rejected «Рад шуд». Чизе хато рафт, промис сабаб (хато) дорад. Колбэки catch даъват мешавад.
Муҳим: промис аз pending ба ҳолати дигар як маротиба ва ба таври абадӣ мегузарад. Промиси иҷрошударо баъдтар «рад кардан» мумкин нест.
Сохтани промис
Промисро тавассути new Promise месозанд. Ба конструктор функсия бо ду параметр дода мешавад: resolve (ҳангоми муваффақият даъват мешавад) ва reject (ҳангоми хато даъват мешавад).
Промисе, ки баъд аз 300 мс иҷро мешавад · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const orderPlov = new Promise ((resolve, reject) => {
setTimeout (() => {
resolve ("Плов готов!" ); // муваффақият: қиматро мемонем
}, 300 );
});
orderPlov.then ((result) => {
console.log ("Получили:" , result);
});
console.log ("Промис создан, ждём…" );
Промисе, ки рад мешавад · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
function buyTicket (balance) {
return new Promise ((resolve, reject) => {
if (balance >= 3 ) {
resolve ("Билет куплен" );
} else {
reject (new Error ("Недостаточно сомони" ));
}
});
}
buyTicket (10 )
.then ((text) => console.log (text))
.catch ((error) => console.log ("Ошибка:" , error.message));
buyTicket (1 )
.then ((text) => console.log (text))
.catch ((error) => console.log ("Ошибка:" , error.message));
then, catch, finally
.then(onSuccess) — вақте иҷро мешавад, ки промис иҷро шуда бошад;
.catch(onError) — вақте иҷро мешавад, ки промис рад шуда бошад (ё дар ягон ҷои боло дар занҷир хато рух дода бошад);
.finally(fn) — дар ҳар сурат иҷро мешавад: барои баъд аз кор «ҷамъ кардан» (нишондиҳандаи боркуниро нест кардан).
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((resolve) => setTimeout (resolve, ms));
console.log ("Показываем «Загрузка...»" );
wait (300 )
.then (() => console.log ("Данные пришли" ))
.catch (() => console.log ("Ошибка" ))
.finally (() => console.log ("Прячем «Загрузка...»" ));
Функсияи wait дар ин ҷо — омодаи судманд аст. Вай промисе бармегардонад, ки баъд аз вақти додашуда иҷро мешавад. Мо онро дар дарс пайваста истифода мебарем.
Занҷираҳои промисҳо
Қуввати асосии промисҳо: then промиси нав бармегардонад . Барои ҳамин then-ҳоро ба занҷир пайваст кардан мумкин аст, қимате ки як then баргардонд, ба оянда мерасад.
Ҳар then натиҷаи қаблиро мегирад · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
Promise.resolve (5 )
.then ((n) => {
console.log ("Получили:" , n);
return n * 2 ; // ин қимат минбаъд меравад
})
.then ((n) => {
console.log ("Удвоили:" , n);
return n + 1 ;
})
.then ((n) => {
console.log ("Прибавили 1:" , n);
});
Агар колбэки then промис баргардонад, занҷир анҷоми онро интизор мешавад ва танҳо баъд минбаъд меравад. Ба ин тартиб қадамҳои пайдарпай сохта мешаванд ва пирамидаи колбэкҳо аз қисми гузашта ба сутуни ҳамвор табдил меёбад:
Ҳамон чор қадам, аммо бе пирамида · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((resolve) => setTimeout (resolve, ms));
function step (name) {
return wait (100 ).then (() => console.log ("Готово:" , name));
}
step ("нашли пользователя" )
.then (() => step ("загрузили заказы" ))
.then (() => step ("узнали адрес" ))
.then (() => step ("посчитали доставку" ))
.then (() => console.log ("Всё готово!" ));
Хатоҳо дар занҷир
Агар дар ягон ҳалқа хато рух диҳад (reject ё throw), занҷир ҳамаи then-ҳои баъдиро мепарронад ва ба наздиктарин catch «меафтад». Як catch дар охир хатоҳои ҳамаи қадамҳоро дастгир мекунад. Агар catch қимат баргардонад — занҷир боз муваффақ ҳисоб мешавад ва минбаъд меравад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
Promise.resolve ("шаг 1" )
.then ((v) => {
console.log (v, "выполнен" );
throw new Error ("шаг 2 сломался" );
})
.then (() => console.log ("этот then пропущен" ))
.catch ((error) => {
console.log ("Поймали:" , error.message);
return "запасной вариант" ;
})
.then ((v) => console.log ("Цепочка продолжилась:" , v));
Хатои маъмул: return-ро дар then фаромӯш кардан
Агар дар колбэки then return набошад, then-и оянда undefined мегирад. Агар дар дохили then қадами нави ғайрисинхронӣ оғоз шавад ва онро барнагардонанд — занҷир онро интизор намешавад.
Нарх гум шуд · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
Promise.resolve (100 )
.then ((price) => {
price * 2 ; // ✖ ҳисоб кардем, аммо барнагардондем
})
.then ((result) => {
console.log ("Результат:" , result); // → undefined
});
Якчанд промис якбора
Мешавад, ки якчанд чизи новобастаро бор кардан лозим мешавад. Агар онҳоро ба навбат интизор шавем — вақт гум мекунем. Беҳтар аст ҳамаро якбора оғоз кунем.
Promise.all([…]) — ҳама -ро интизор мешавад. Массиви натиҷаҳоро бо ҳамон тартиб , ки дар дархост буд, бармегардонад. Агар ақаллан як промис рад шавад — пурра рад мешавад;
Promise.allSettled([…]) — ҳамаро интизор мешавад ва ҳаргиз рад намешавад: барои ҳар кадом status ("fulfilled" ё "rejected") ва value / reason-ро хабар медиҳад;
Promise.race([…]) — натиҷа (ё хатои) аз ҳама тез -ро.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms, value) => new Promise ((resolve) => setTimeout (() => resolve (value), ms));
Promise.all ([
wait (300 , "курсы валют" ),
wait (100 , "погода" ),
wait (200 , "новости" ),
]).then ((results) => {
console.log ("Всё загружено:" , results.join (", " )); // тартиб мисли дархост
});
Promise.race ([wait (300 , "медленный" ), wait (100 , "быстрый" )])
.then ((winner) => console.log ("Первым пришёл:" , winner));
Муфассалтар хонед: learn.javascript.ru — Промисҳо · learn.javascript.ru — Занҷири промисҳо · MDN — Promise
Амал: мустаҳкам мекунем
Промис месозем, занҷир мебандем, хатоҳоро дастгир мекунем, якчанд промисро баробар оғоз мекунем.
ВАЗИФАИ 4.1 Промиси аввалин осон
Промисе созед, ки баъд аз 200 мс бо қимати "Данные загружены" иҷро мешавад. Қиматро тавассути then чоп кунед.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
// const loading = new Promise(...)
// loading.then(...)
Натиҷаи интизоршаванда Данные загружены
Ишора 1 new Promise((resolve) => { ... }) — дар дохил setTimeout-ро барои 200 мс оғоз кунед.
Ишора 2 Дар дохили таймер resolve("Данные загружены")-ро даъват кунед. Қимате, ки ба resolve дода шуд, ба колбэки then мерасад.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 4.2 Санҷиши дастрасӣ осон
Функсияи checkAdult промис бармегардонад. Натиҷаро барои синни 15 коркард кунед: Ошибка: …-ро бо матни сабаб чоп кунед, дар охир бошад — «проверка завершена». Сипас синнро ба 20 иваз кунед ва бинед, чӣ тағйир меёбад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
function checkAdult (age) {
return new Promise ((resolve, reject) => {
if (age >= 18 ) {
resolve ("доступ разрешён" );
} else {
reject (new Error ("доступ закрыт" ));
}
});
}
// checkAdult(15) ...
Натиҷаи интизоршаванда Ошибка: доступ закрыт
проверка завершена
Ишора 1 Занҷири се усул: .then(...) барои муваффақият, .catch(...) барои хато ва .finally(...) дар охир.
Ишора 2 Сабаби радшавӣ дар error.message аст: .catch((error) => console.log("Ошибка: " + error.message)).
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 4.3 Занҷири тахфифҳо миёна
Куртка 1000 сомонӣ меарзад. Занҷири аз ду then созед: аввалӣ тахфифи 10%-ро татбиқ мекунад ва После скидки: …-ро чоп мекунад, дуюмӣ купони 50 сомониро кам мекунад ва С купоном: …-ро чоп мекунад. Ҳар қадам бояд нархи навро баргардонад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const price = 1000 ;
// Promise.resolve(price)...
Натиҷаи интизоршаванда После скидки: 900
С купоном: 850
Ишора 1 Аз Promise.resolve(price) оғоз кунед. Ҳар then нархро аз қаблӣ мегирад.
Ишора 2 Қолаби қадам: .then((p) => { const next = p * 0.9; console.log("После скидки: " + next); return next; }). Қадами дуюм ҳамин тавр сохта шудааст, аммо 50-ро кам мекунад.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 4.4 Хаторо ёб: return-и гумшуда осон
Бояд «Итого: 120» чоп шавад (нархи 100 плюс расонидани 20), аммо undefined чоп мешавад. Кодро ислоҳ кунед.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
Promise.resolve (100 )
.then ((price) => {
const total = price + 20 ;
})
.then ((total) => {
console.log ("Итого: " + total);
});
Натиҷаи интизоршаванда Итого: 120
Ишора 1 then-и дуюм чӣ мегирад? Танҳо он чиро, ки аввалӣ баргардонд .
Ишора 2 Ба then-и аввал сатри return total;-ро илова кунед.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 4.5 Боркунии саҳифаи асосӣ миёна
Се боркунии новобаста 300, 100 ва 200 мс мегиранд. Онҳоро якбора тавассути Promise.all оғоз кунед ва як сатр чоп намоед, чунон ки дар мисол аст.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms, value) => new Promise ((resolve) => setTimeout (() => resolve (value), ms));
const loadProfile = () => wait (300 , "профиль" );
const loadOrders = () => wait (100 , "заказы" );
const loadBanners = () => wait (200 , "баннеры" );
// Promise.all([...]).then(...)
Натиҷаи интизоршаванда Загружено: профиль, заказы, баннеры
Ишора 1 Ба Promise.all массиви даъватҳои функсияҳо дода мешавад: [loadProfile(), loadOrders(), loadBanners()].
Ишора 2 Ба then массиви натиҷаҳо бо ҳамон тартибе, ки дар дархост буд, мерасад. Онро тавассути .join(", ") пайваст кунед.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 4.6 Чӣ бор шуд, чӣ не душвор
Яке аз се дархост барор нагирифт, аммо боқиро бояд нишон дод. Дар then массиви натиҷаҳоро гиред ва барои ҳар кадом ✓ қимат (агар status === "fulfilled") ё ✗ сабаб (агар "rejected", сабаб — reason.message) чоп кунед.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms, value) => new Promise ((resolve) => setTimeout (() => resolve (value), ms));
const fail = (ms, message) => new Promise ((_, reject) => setTimeout (() => reject (new Error (message)), ms));
Promise.allSettled ([
wait (100 , "курс" ),
fail (150 , "нет сети" ),
wait (50 , "расписание" ),
]).then ((results) => {
// барои ҳар натиҷа як сатр чоп кунед
});
Натиҷаи интизоршаванда ✓ курс
✗ нет сети
✓ расписание
Ишора 1 results.forEach((item) => { ... })-ро истифода баред. Ҳар унсур майдони status дорад.
Ишора 2 Агар item.status === "fulfilled" бошад — қимат дар item.value, вагарна сабаб дар item.reason.message. Тартиби натиҷаҳо — мисли дар массиви дархост, на ба тартиби анҷомёбии онҳо.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 4.7 Тартибро пешгӯӣ кун: занҷир бо хато миёна
Хато дар занҷир, catch, ки қимат бармегардонад ва finally. Дар бораи сатри синхронии log("f") дар охир фаромӯш накунед.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const actual = [];
const log = (label) => actual.push (label);
Promise.resolve ("a" )
.then ((v) => {
log (v);
throw new Error ("сбой" );
})
.then (() => log ("b" ))
.catch (() => {
log ("c" );
return "d" ;
})
.then ((v) => log (v))
.finally (() => log ("e" ));
log ("f" );
const prediction = [];
// --- санҷиш, тағйир надиҳед ---
setTimeout (() => console.log (actual.join (" " ) === prediction.join (" " ) ? "Верно!" : "Не угадали, подумайте ещё" ), 400 );
Натиҷаи интизоршаванда Верно!
Ишора 1 Ба таври синхронӣ танҳо log("f") иҷро мешавад. Ҳамаи ҳалқаҳои дигари занҷир — микровазифаҳо мебошанд, ки яке аз паси дигаре саф кашидаанд.
Ишора 2 Баъд аз throw ҳалқа бо нишонаи b гузаронда мешавад — вай даъват намегардад. catch «d»-ро бармегардонад ва занҷир ҳамчун муваффақ идома меёбад.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
05 async / await: промисҳо бе занҷирҳо
Занҷирҳои then аз пирамида беҳтаранд, аммо боз ҳам мисли коди оддӣ хонда намешаванд. Дар JavaScript синтаксисе ҳаст, ки коди ғайрисинхрониро ба синхронӣ монанд мекунад: async / await. Дар зери сарпӯш ин ҳамон промисҳост, фақат бароҳаттар навишта шудаанд.
async Калима пеш аз функсия. Чунин функсия ҳамеша промис бармегардонад ва дар дохили он await-ро истифода бурдан мумкин аст.
await «Натиҷаи промисро интизор шав». Танҳо дар дохили функсияи async кор мекунад. Ҳамин функсияро боздошта мемонад, на тамоми барномаро.
Ҳамон қадамҳо: аввал тавассути then, баъд тавассути await · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((resolve) => setTimeout (resolve, ms));
// буд: занҷири then
function checkoutThen () {
return wait (100 )
.then (() => console.log ("then: корзина открыта" ))
.then (() => wait (100 ))
.then (() => console.log ("then: оплата прошла" ));
}
// шуд: async / await
async function checkout () {
await wait (100 );
console.log ("await: корзина открыта" );
await wait (100 );
console.log ("await: оплата прошла" );
}
checkoutThen ().then (() => checkout ());
Коди бо await аз боло ба поён мисли синхронии оддӣ хонда мешавад: «интизор шудем, чоп кардем, интизор шудем, чоп кардем». Натиҷаи промисро оддӣ ба тағйирёбанда гузоштан мумкин аст:
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms, value) => new Promise ((resolve) => setTimeout (() => resolve (value), ms));
async function showPrice () {
console.log ("Спрашиваем цену..." );
const price = await wait (200 , 35 ); // await қиматро аз промис «мебарорад»
console.log ("Цена плова:" , price, "сомони" );
return price * 2 ;
}
showPrice ().then ((double) => console.log ("Две порции:" , double));
console.log ("showPrice() запущена и вернула промис" );
Қиёс аз ҳаёт
Шумо дар навбати нон меистед. await — ин «ба навбат истодӣ ва ҳиссаи худро интизорӣ». Аммо корҳои дигари кӯча (тамоми боқимондаи коди барнома) намеистанд: танҳо шумо, як функсия, интизор мешавед. Нон тайёр шуд — шумо аз ҳамон ҷое, ки истода будед, идома медиҳед.
Хатоҳо: try / catch / finally
Агар промис рад шавад, await дар ҳамон ҷое, ки шумо интизор будед, хато мепартояд . Онро бо try / catch-и маъмулӣ, ки аллакай медонед, дастгир мекунем. finally дар ҳар сурат иҷро мешавад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((resolve) => setTimeout (resolve, ms));
async function loadStudent (id) {
await wait (100 );
if (id <= 0 ) {
throw new Error ("неверный номер студента" );
}
return "Студент №" + id;
}
async function main () {
try {
console.log (await loadStudent (5 ));
console.log (await loadStudent (0 )); // инҷо хато мешавад
console.log ("эта строка не выполнится" );
} catch (error) {
console.log ("Ошибка:" , error.message);
} finally {
console.log ("Загрузка завершена" );
}
}
main ();
Пай дар пай ё мувозӣ
Ҳар await интизор мешавад, то қадами қаблӣ анҷом ёбад. Агар қадамҳо новобаста бошанд — ин талафи вақт аст: ду боркунии 200 мс-а пай дар пай 400 мс мегиранд. Ҳарду промисро якбора оғоз кунед ва онҳоро якҷоя тавассути Promise.all интизор шавед — 200 мс мешавад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms, value) => new Promise ((resolve) => setTimeout (() => resolve (value), ms));
async function sequential () {
console.log ("--- последовательно ---" );
const a = await wait (200 , "курсы" ); // 200 мс интизор мешавем
const b = await wait (200 , "новости" ); // баъд боз 200 мс
console.log ("получили:" , a, b);
}
async function parallel () {
console.log ("--- параллельно ---" );
const [a, b] = await Promise.all ([wait (200 , "курсы" ), wait (200 , "новости" )]); // 200 мс якҷоя
console.log ("получили:" , a, b);
}
sequential ().then (parallel);
Хатоҳои маъмул
1. await берун аз функсияи async — хатои синтаксисӣ аст. 2. await-ро фаромӯш кардан: ба ҷои қимат худи промисро мегиред. 3. try / catch-ро фаромӯш кардан: хато ҳамчун коркарднашуда ба берун «парвоз мекунад».
Хато: await-ро фаромӯш кардем · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms, value) => new Promise ((resolve) => setTimeout (() => resolve (value), ms));
async function main () {
const price = wait (100 , 35 ); // ✖ бе await
console.log ("Цена:" , price); // → Цена: Promise {…}, на 35
}
main ();
await ва event loop
Ҳар чизе, ки баъд аз await меояд — идомаи функсия дар намуди микровазифа аст. Коди то аввалин await ба таври синхронӣ иҷро мешавад, боқимонда бошад ба навбати микровазифаҳо «меистад»:
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
async function main () {
console.log ("1. до await (синхронно)" );
await null ;
console.log ("3. после await (микрозадача)" );
}
main ();
console.log ("2. после вызова main() (синхронно)" );
Муфассалтар хонед: learn.javascript.ru — Async/await · MDN — Истифодаи промисҳо
Амал: мустаҳкам мекунем
Функсияҳои async менависем, хатоҳоро дастгир мекунем ва қадамҳои новобастаро тезонем.
ВАЗИФАИ 5.1 Ба async/await бознависед осон
Функсияи checkoutOld тавассути занҷири then навишта шудааст ва даъват намешавад. Функсияи async function checkout()-ро нависед, ки ҳамин корро тавассути await мекунад ва онро даъват кунед.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((resolve) => setTimeout (resolve, ms));
function checkoutOld () {
return wait (100 )
.then (() => { console.log ("Шаг 1: открыли корзину" ); return wait (100 ); })
.then (() => { console.log ("Шаг 2: выбрали доставку" ); return wait (100 ); })
.then (() => console.log ("Шаг 3: оплатили" ));
}
// async function checkout() { ... }
Натиҷаи интизоршаванда Шаг 1: открыли корзину
Шаг 2: выбрали доставку
Шаг 3: оплатили
Ишора 1 Ҳар .then(() => ...) ба сатр табдил меёбад: аввал await wait(100), баъд console.log(...).
Ишора 2 Бадан: await wait(100); console.log("Шаг 1: ..."); await wait(100); console.log("Шаг 2: ..."); await wait(100); console.log("Шаг 3: ..."); — ва даъват кардани checkout()-ро фаромӯш накунед.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 5.2 Тартибро пешгӯӣ кун: await осон
Коди баъд аз await — микровазифа аст. Бо нишонаҳои 1, 2, 3, 0 чӣ мешавад?
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const actual = [];
const log = (label) => actual.push (label);
async function main () {
log ("1" );
await null ;
log ("2" );
}
log ("0" );
main ();
log ("3" );
const prediction = [];
// --- санҷиш, тағйир надиҳед ---
setTimeout (() => console.log (actual.join (" " ) === prediction.join (" " ) ? "Верно!" : "Не угадали, подумайте ещё" ), 400 );
Натиҷаи интизоршаванда Верно!
Ишора 1 Функсияи main() ба таври синхронӣ то аввалин await иҷро мешавад.
Ишора 2 Нишонаи 2 баъд аз await меистад — ин микровазифа аст, вай вақте иҷро мешавад, ки тамоми коди синхронӣ, аз ҷумла log("3"), анҷом ёбад.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 5.3 Рӯйхати донишҷӯён бо хато миёна
Функсияи fetchStudent барои рақами 0 хато мепартояд. Функсияи async-и main-ро нависед: вай ба навбат (дар давраи for…of) донишҷӯёни 1, 0 ва 2-ро бор мекунад. Натиҷаро чунон ки ҳаст, хаторо бошад ҳамчун Ошибка: … чоп мекунад. Баъд аз ҳар дархост, муваффақ ё не, — запрос завершён чоп мешавад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((resolve) => setTimeout (resolve, ms));
async function fetchStudent (id) {
await wait (50 );
if (id === 0 ) {
throw new Error ("студент не найден" );
}
return "Студент №" + id;
}
// async function main() { ... }
// main();
Натиҷаи интизоршаванда Студент №1
— запрос завершён
Ошибка: студент не найден
— запрос завершён
Студент №2
— запрос завершён
Ишора 1 Дар дохили давра try / catch / finally-и худӣ лозим аст — он гоҳ хатои як дархост боқиро қатъ намекунад.
Ишора 2 for (const id of [1, 0, 2]) { try { console.log(await fetchStudent(id)); } catch (error) { console.log("Ошибка: " + error.message); } finally { console.log("— запрос завершён"); } }
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 5.4 Боркуниро тезон миёна
Ду боркунии новобаста ҳоло яке аз паси дигаре мераванд. main-ро чунон дигар кунед, ки ҳарду якбора оғоз шаванд (Promise.all). Он гоҳ «новости» (тезтар) пештар аз «курсы» анҷом меёбад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((resolve) => setTimeout (resolve, ms));
async function load (name, ms) {
console.log ("старт " + name);
await wait (ms);
console.log ("готов " + name);
return name;
}
async function main () {
const a = await load ("курсы" , 200 );
const b = await load ("новости" , 100 );
console.log ("итого: " + a + " + " + b);
}
main ();
Натиҷаи интизоршаванда старт курсы
старт новости
готов новости
готов курсы
итого: курсы + новости
Ишора 1 await-ро барои ҳар боркунӣ ҷудогона истифода набаред. Ҳарду функсияро якбора оғоз кунед ва ба Promise.all диҳед.
Ишора 2 const [a, b] = await Promise.all([load("курсы", 200), load("новости", 100)]); — массиви натиҷаҳо бо ҳамон тартибе, ки дар дархост буд, меояд.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 5.5 Кӯшишро такрор кун душвор
Сервер баъзан «меафтад». async function retry(fn, times)-ро нависед: вай fn-ро то times маротиба даъват мекунад. Агар кӯшиш ноком шавад — попытка N: сообщение-ро чоп мекунад ва боз кӯшиш мекунад. Агар ҳама ноком шаванд — хатои охиринро мепартояд. Функсияи flaky махсус ду бор вайрон мешавад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((resolve) => setTimeout (resolve, ms));
let calls = 0 ;
async function flaky () {
calls++;
await wait (50 );
if (calls < 3 ) {
throw new Error ("сбой " + calls);
}
return "данные" ;
}
// async function retry(fn, times) { ... }
retry (flaky, 5 ).then ((result) => console.log ("успех: " + result));
Натиҷаи интизоршаванда попытка 1: сбой 1
попытка 2: сбой 2
успех: данные
Ишора 1 Давраи for (let i = 1; i <= times; i++), дар дохилаш бошад — try { return await fn(); } catch (error) { … }.
Ишора 2 Дар catch: `попытка ${i}: ${error.message}`-ро чоп кунед. Агар i === times бошад, throw error нависед — вагарна давра оддӣ ба кӯшиши навбатӣ мегузарад.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 5.6 Абадӣ интизор нашав душвор
withTimeout(promise, ms)-ро нависед: тавассути Promise.race вай натиҷаи промисро бармегардонад, агар расида бошад, ё бо хатои таймаут рад мешавад, агар аз ms мс зиёдтар гузашта бошад. Функсияи test аллакай навишта шудааст.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms, value) => new Promise ((resolve) => setTimeout (() => resolve (value), ms));
// function withTimeout(promise, ms) { ... }
async function test (label, delay) {
try {
console.log (await withTimeout (wait (delay, "ответ " + label), 150 ));
} catch (error) {
console.log ("Ошибка: " + error.message);
}
}
test ("быстрый" , 50 ).then (() => test ("медленный" , 400 ));
Натиҷаи интизоршаванда ответ быстрый
Ошибка: таймаут
Ишора 1 «Мусобиқа» байни промиси шумо ва промиси дуюм лозим аст, ки оддӣ баъд аз ms миллисония рад мешавад.
Ишора 2 return Promise.race([promise, new Promise((_, reject) => setTimeout(() => reject(new Error("таймаут")), ms))]);
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 5.7 Тартибро пешгӯӣ кун: финал душвор
Ҳама якҷоя: функсияҳои async, await, then ва таймер. Ба ёд оред: функсияи b() ба таври синхронӣ то охир иҷро мешавад ва промиси аллакай иҷрошударо бармегардонад, await бошад идоракуниро ба берун медиҳад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const actual = [];
const log = (label) => actual.push (label);
async function a () {
log ("a1" );
await b ();
log ("a2" );
}
async function b () {
log ("b1" );
}
setTimeout (() => log ("t" ), 0 );
a ();
Promise.resolve ().then (() => log ("p" ));
log ("s" );
const prediction = [];
// --- санҷиш, тағйир надиҳед ---
setTimeout (() => console.log (actual.join (" " ) === prediction.join (" " ) ? "Верно!" : "Не угадали, подумайте ещё" ), 400 );
Натиҷаи интизоршаванда Верно!
Ишора 1 Ба таври синхронӣ: a() то await иҷро мешавад ва b()-ро пурра даъват мекунад (нишонаҳои a1, b1). Баъд then сабт мешавад ва log("s") иҷро мегардад.
Ишора 2 Микровазифаҳо бо тартиби илова шудан мераванд: аввал идомаи функсияи a (вай дар await ба навбат истод), баъд then бо нишонаи p. Таймер — охирин.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
06 Блоки ЗС: event loop-ро шарҳ медиҳем ва бо код месанҷем
Ғайрисинхронӣ — яке аз мавзӯъҳоест, ки ЗС (зеҳни сунъӣ) онро зебо шарҳ медиҳад, аммо баъзан дар ҷузъиёт хато мекунад: тартиби микровазифаҳо ва таймерҳоро омехта мекунад ё дар бораи await «фаромӯш мекунад». Имрӯз малакаи асосии кор бо ЗС-ро машқ мекунем: бовар накардан ба гап, балки бо иҷро санҷидан .
Қоидаҳои курс, ки дар ин ҷо махсусан муҳиманд
1. Аввал 15 дақиқа худатон кӯшиш мекунед: кодро ба сабадҳо (синхронӣ / микровазифаҳо / макровазифаҳо) тақсим кунед ва пешгӯии тартиби чопи худро нависед. 2. Танҳо баъд ба сӯи ЗС мераванд. 3. Ба лоиҳаи худ коде гузоред, ки онро сатр ба сатр шарҳ дода наметавонед. 4. Шарҳи ЗС-ро ҳамеша бо иҷро санҷед : код — беҳтарин довар аст.
Чӣ тавр пурсидан: бад ва хуб
Формулаи промпти курс: контекст → вазифа → маҳдудиятҳо → формати ҷавоб → санҷиш .
event loop-ро шарҳ деҳНусха бардоштан
Ман JavaScript меомӯзам, сатҳ — навомӯз, функсияҳо ва массивҳоро медонам, дар бораи промисҳо танҳо оғоз мекунам. Event loop-ро дар мисоли ин код шарҳ деҳ: console.log("A"); setTimeout(() => console.log("B"), 0); Promise.resolve().then(() => console.log("C")); console.log("D"); Тартиби чопро дар консол нишон деҳ ва чаро чунин аст: қадам ба қадам, бо қайди он ки дар стек, дар навбати микровазифаҳо ва дар навбати макровазифаҳо чӣ хобидааст. Бе истилоҳоти мураккаб ва бе мисолҳои дигар. Дар охир 2 хатои маъмули навомӯзонро номбар кун, ки аз сабаби онҳо тартиби чопро нодуруст пешгӯӣ мекунанд.Нусха бардоштан
Промпти хубро ба чати ЗС нусха кунед. Баъд шарҳро бо код санҷед :
Ҷавоби ЗС-ро бо иҷро месанҷем · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
console.log ("A" );
setTimeout (() => console.log ("B" ), 0 );
Promise.resolve ().then (() => console.log ("C" ));
console.log ("D" );
// Оё тартиб бо ҷавоби ЗС мувофиқат кард? Агар не, пас ЗС хато кардааст — ё шумо вазифаро нодуруст тавсиф кардаед.
Дар ҷавоби ЗС чиро санҷидан лозим
1) Оё тартиби чоп бо иҷрои воқеӣ мувофиқат мекунад? 2) Оё навбат барои then ва setTimeout дуруст номбар шудааст? 3) Оё дар мисолҳо коди бегонае нест, ки шумо онро намефаҳмед? 4) Агар ЗС async/await-ро пешниҳод кард, оё дар он try/catch ҳаст?
Амал: хатои ЗС-ро медарёбем
ВАЗИФАИ 6.1 ЗС хато кардааст? Бо иҷро санҷ миёна
ЗС боварӣ бо ҷавоб дод, ки тартиби чоп начало, таймер, промис, конец мешавад. Бовар накунед — санҷед. Кодро ба сабадҳо тақсим кунед, хаторо дар ҷавоби ЗС ёбед ва массиви aiAnswer-ро чунон ислоҳ кунед, ки бо тартиби воқеӣ мувофиқат кунад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const actual = [];
const log = (label) => actual.push (label);
log ("начало" );
setTimeout (() => log ("таймер" ), 0 );
Promise.resolve ().then (() => log ("промис" ));
log ("конец" );
// ҷавоби ЗС — дар он хато ҳаст, ислоҳ кунед
const aiAnswer = ["начало" , "таймер" , "промис" , "конец" ];
// --- санҷиш, тағйир надиҳед ---
setTimeout (() => console.log (actual.join (" " ) === aiAnswer.join (" " ) ? "Верно!" : "ИИ ошибся, исправьте ответ" ), 400 );
Натиҷаи интизоршаванда Верно!
Ишора 1 Сатрҳои синхронӣ — «начало» ва «конец» — бояд аввал раванд.
Ишора 2 Промис — микровазифа аст, вай ҳамеша пештар аз таймер (макровазифа) мебошад.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
07 Амал дар дарс: тақлиди боркунии маълумот
Серверҳои воқеӣ ҳоло надорем (ба онҳо дар дарси оянда мерасем), барои ҳамин сервери «қалбакӣ» месозем — функсияҳое, ки мисли дархостҳои воқеӣ бо таъхир ҷавоб медиҳанд. Ин усули стандартӣ аст: бо ин роҳ интерфейсро то омода шудани сервер месанҷанд.
Қадами 1. Базаи маълумот ва функсияҳои ёрирасон
Аввал «базаи» мо ва функсияи wait. Иҷро кунед — ҳоло чизе чоп намешавад, мо танҳо мавод омода мекунем.
Қадами 1. «Сервер» · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((resolve) => setTimeout (resolve, ms));
const users = {
1 : { name: "Мадина" },
2 : { name: "Фарход" },
};
const orders = {
1 : [120 , 80 , 45 ], // маблағи фармоишҳо бо сомонӣ
2 : [],
};
console.log ("Готово. Пользователей:" , Object.keys (users).length);
Қадами 2. Функсияҳои «дархостҳо»
Ҳар функсия интизор мешавад ва маълумот бармегардонад. Агар корбар набошад — промисро бо хато рад мекунад. Сервери воқеӣ ҳамин тавр рафтор мекунад: аксар вақт вай дар 100–500 мс ҷавоб медиҳад ва гоҳо «хато» мегӯяд.
Қадами 2. Дархостҳо бо таъхир · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((resolve) => setTimeout (resolve, ms));
const users = { 1 : { name: "Мадина" }, 2 : { name: "Фарход" } };
const orders = { 1 : [120 , 80 , 45 ], 2 : [] };
async function fakeFetchUser (id) {
await wait (200 );
const user = users[id];
if (!user) {
throw new Error ("пользователь не найден" );
}
return user;
}
async function fakeFetchOrders (id) {
await wait (150 );
return orders[id] ?? [];
}
fakeFetchUser (1 ).then ((user) => console.log ("Получили:" , user.name));
fakeFetchUser (99 ).catch ((error) => console.log ("Ошибка:" , error.message));
Қадами 3. Занҷир: корбар → фармоишҳои ӯ
Фармоишҳо аз корбар вобастаанд, барои ҳамин ба навбат интизор мешавем. Тавассути async/await ин мисли дастур хонда мешавад:
Қадами 3. Дархостҳои вобаста · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((resolve) => setTimeout (resolve, ms));
const users = { 1 : { name: "Мадина" }, 2 : { name: "Фарход" } };
const orders = { 1 : [120 , 80 , 45 ], 2 : [] };
async function fakeFetchUser (id) {
await wait (200 );
if (!users[id]) throw new Error ("пользователь не найден" );
return users[id];
}
async function fakeFetchOrders (id) {
await wait (150 );
return orders[id] ?? [];
}
async function showProfile (id) {
const user = await fakeFetchUser (id);
const list = await fakeFetchOrders (id);
const sum = list.reduce ((total, price) => total + price, 0 );
console.log (`${user.name}: заказов ${list.length}, на ${sum} сомони` );
}
showProfile (1 );
Қадами 4. Инро дар саҳифа нишон медиҳем
Дар браузер мо одатан ба корбар се ҳолатро нишон медиҳем: «Боркунӣ…» , маълумот ё хато . Дар барномаи хурди поён «Загрузить»-ро пахш кунед, баъд ҷадвали script.js-ро кушоед ва рақами корбарро ба 99 иваз кунед — ҳолати хаторо мебинед. Ба ин усул мо дар дарси 17 бармегардем.
Профил бо нишондиҳандаи боркунӣ · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
index.html style.css script.js
< div class ="card" >
< button id ="load" > Загрузить профиль</ button >
< p id ="status" > Нажмите кнопку</ p >
</ div >
.card { max-width : 320px ; padding : 16px ; border : 1px solid #ccd ; border-radius : 12px ; }
button { padding : 8px 14px ; border-radius : 8px ; border : 0 ; background : #1a8a6a ; color : #fff ; font-size : 15px ; cursor : pointer; }
#status { margin : 12px 0 0 ; }
.error { color : #c0392b ; }
const wait = (ms) => new Promise ((resolve) => setTimeout (resolve, ms));
const users = { 1 : { name: "Мадина" }, 2 : { name: "Фарход" } };
async function fakeFetchUser (id) {
await wait (600 );
if (!users[id]) throw new Error ("пользователь не найден" );
return users[id];
}
const button = document.querySelector ("#load" );
const status = document.querySelector ("#status" );
button.addEventListener ("click" , async () => {
status.className = "" ;
status.textContent = "Загрузка..." ;
button.disabled = true ;
try {
const user = await fakeFetchUser (1 ); // ба 99 иваз кунед
status.textContent = "Привет, " + user.name + "!" ;
} catch (error) {
status.className = "error" ;
status.textContent = "Ошибка: " + error.message;
} finally {
button.disabled = false ;
}
console.log ("статус:" , status.textContent);
});
Пешнамоиш Пӯшонидан
Барои дидани натиҷа «Иҷро кардан»-ро пахш кунед.
Амал: дашборд ҷамъ мекунем
ВАЗИФАИ 7.1 Дашборди корбар миёна
async function loadDashboard(id)-ро нависед: вай «Загрузка...»-ро чоп мекунад, баъд корбар ва фармоишҳои ӯро якбора мегирад (Promise.all — онҳо аз ҳам вобаста нестанд, танҳо id лозим аст) ва сатри Привет, имя! Заказов: N, на сумму S сомони-ро чоп мекунад.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((resolve) => setTimeout (resolve, ms));
const users = { 1 : { name: "Мадина" }, 2 : { name: "Фарход" } };
const orders = { 1 : [120 , 80 , 45 ], 2 : [] };
async function fakeFetchUser (id) {
await wait (200 );
if (!users[id]) throw new Error ("пользователь не найден" );
return users[id];
}
async function fakeFetchOrders (id) {
await wait (150 );
return orders[id] ?? [];
}
// async function loadDashboard(id) { ... }
loadDashboard (1 );
Натиҷаи интизоршаванда Загрузка...
Привет, Мадина! Заказов: 3, на сумму 245 сомони
Ишора 1 const [user, list] = await Promise.all([fakeFetchUser(id), fakeFetchOrders(id)]);
Ишора 2 Маблағи фармоишҳо: list.reduce((total, price) => total + price, 0). Сатрро бо нохунакҳои қолабӣ ҷамъ кардан қулай аст.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
ВАЗИФАИ 7.2 Боркунӣ бо хато душвор
loadDashboard-ро такмил диҳед: агар корбар ёфт нашавад, ба ҷои салом Ошибка: …-ро чоп кунед. Дар ҳар сурат, муваффақият ё хато, дар охир «Загрузка завершена» чоп мешавад. Функсияро барои корбарони 1 ва 99 ба навбат (баъд аз анҷоми якум) иҷро кунед.
Таҳрир кардан мумкин аст · Ctrl + Enter ↺ Аз нав ▶ Иҷро кардан
const wait = (ms) => new Promise ((resolve) => setTimeout (resolve, ms));
const users = { 1 : { name: "Мадина" }, 2 : { name: "Фарход" } };
const orders = { 1 : [120 , 80 , 45 ], 2 : [] };
async function fakeFetchUser (id) {
await wait (200 );
if (!users[id]) throw new Error ("пользователь не найден" );
return users[id];
}
async function fakeFetchOrders (id) {
await wait (150 );
return orders[id] ?? [];
}
// async function loadDashboard(id) { ... }
// барои 1 иҷро кунед, вақте анҷом ёфт — барои 99
Натиҷаи интизоршаванда Загрузка...
Привет, Мадина! Заказов: 3, на сумму 245 сомони
Загрузка завершена
Загрузка...
Ошибка: пользователь не найден
Загрузка завершена
Ишора 1 Бадани функсия: «Загрузка...», баъд try { ... } catch (error) { ... } finally { ... }.
Ишора 2 Барои ба навбат иҷро кардан занҷирро истифода баред: loadDashboard(1).then(() => loadDashboard(99)); — функсия промис бармегардонад, чунки вай async аст.
○ Ҳалшуда қайд кардан 💬 Дар бораи ин вазифа пурсидан
08 Вазифаи хонагӣ
Шаш вазифа дар мавзӯи промисҳо ва async/await. Ҳамаи ҳалҳо — дар як файли async-basics.js. Пеш аз ҳар ҳал шарҳе бо рақами вазифа гузоред.
Таймер бо промисҳо. Функсияи delay(ms)-ро нависед, ки промисе бармегардонад, ки баъд аз ms миллисония иҷро мешавад. Бо ёрии он «3», «2», «1», «Старт!»-ро бо танаффуси 300 мс байни сатрҳо (тавассути занҷири then) чоп кунед.
Аз колбэк ба промис. Функсияи checkAge(age, callback)-ро аз вазифаи 2.2 гиред ва печонандаи checkAgeAsync(age)-ро нависед, ки промис бармегардонад. Онро барои ду синну сол даъват кунед, натиҷаро тавассути then / catch коркард намоед.
Занҷири се қадам. Се қадами «фармоиши питса» бо таъхир: фармоишро қабул кардан → тайёр кардан → расондан. Ҳар кадом промис бо сатр бармегардонад. Онҳоро ба занҷири ҳамвор саф кашед ва натиҷаи ҳар қадамро чоп кунед. Дар охир як catch илова кунед ва санҷед, ки он кор мекунад, агар як қадамро маҷбур кунед, ки рад шавад.
Се боркунӣ якбора. Се «дархост» бо таъхири гуногун (қурби сомонӣ, обу ҳаво дар Душанбе, ҷадвали гурӯҳ). Тавассути Promise.all оғоз кунед, натиҷаҳо ва вақти умумиро чоп намоед (Date.now() то ва баъд — вай бояд тақрибан ба дарозтарин таъхир баробар бошад, на ба маҷмӯъ).
async / await бо хато. async function loadProfile(id)-ро нависед, ки профилро 300 мс «бор мекунад» ва барои рақами калонтар аз 100 хато мепартояд. Онро барои се рақам даъват кунед, хатоҳоро тавассути try / catch / finally дастгир намоед.
Варақаи пешгӯиҳо. Се порчаи кодии худатонро бо омехтаи console.log, setTimeout ва Promise.then ихтироъ кунед. Болои ҳар кадом пешгӯии тартиби чопи худро ҳамчун шарҳ нависед, баъд иҷро кунед ва муқоиса намоед. Агар дуруст пешгӯӣ накардед — дар як сатр шарҳ диҳед, ки хато дар чӣ буд.
Чӣ супоридан лозим
Файли async-basics.js бо ҳамаи шаш ҳал ва шарҳҳо.
Истинод ба репозиторий дар GitHub (ё худи файл — чунон ки бо муаллим мувофиқа кунед).
Чӣ тавр баҳо медиҳем (0–10)
Чӣ Холҳо Вазифаҳои 1–2 кор мекунанд ва натиҷаи интизоршавандаро чоп мекунанд 2 Вазифаи 3: занҷири ҳамвор, catch воқеан кор мекунад 2 Вазифаи 4: дархостҳо якбора мераванд, вақт тақрибан ба дарозтарин таъхир баробар аст 2 Вазифаи 5: try / catch / finally дар ҷояш аст ва хатоҳоро дастгир мекунад 2 Вазифаи 6: пешгӯиҳои софдилона, хатоҳо таҳлил шудаанд 2
Пеш аз супоридан
Барои ҳар функсия аз худ пурсед: «Оё метавонам шарҳ диҳам, ки ҳар сатр дар кадом навбат иҷро мешавад?» Агар ЗС-ро истифода бурда бошед — ҳар сатрро бояд дар ҳимоя шарҳ дода тавонед.
✓ Лавҳаи ёддошти дарс
Коди синхронӣ сатр ба сатр меравад. Ғайрисинхронӣ корро оғоз мекунад ва интизор намешавад: натиҷа баъдтар меояд.
setTimeout(fn, мс) — як маротиба баъдтар иҷро кардан; setInterval — такрор кардан; қатъкунӣ — clearTimeout / clearInterval. Функсия -ро месупорем, на даъвати онро.
Callback — функсияе, ки «баъдтар» даъват мешавад. Колбэки «error-first»: (error, result). Колбэкҳои бисёри дохилшуда — «дӯзахи колбэкҳо».
Promise : pending → fulfilled / rejected, як маротиба тағйир меёбад. Сохтан: new Promise((resolve, reject) => …).
then / catch / finally : then промиси нав бармегардонад, қимат дар занҷир мерасад (return лозим аст); хато then-ро то наздиктарин catch мепарронад; finally — ҳамеша.
Promise.all — ҳама якҷоя (тартиб мисли дар дархост, як хато — ҳама рад мешавад); allSettled — ҳисобот аз рӯи ҳар кадом; race — тезтарин.
Функсияи async ҳамеша промис бармегардонад. await натиҷаро танҳо дар дохили async интизор мешавад; хатоҳоро бо try / catch / finally дастгир мекунем. Қадамҳои новобаста — тавассути Promise.all.
Event loop: аввал тамоми коди синхронӣ → ҳамаи микровазифаҳо (then, баъд аз await, queueMicrotask) → як макровазифа (setTimeout) → боз микровазифаҳо.
Бо ЗС: аввал худатон, баъд промпт аз рӯи формула. Шарҳи ЗС дар бораи тартиби чопро — ҳамеша бо иҷро месанҷем.