09 β Asinxron Dart¶
β¬ οΈ Oldingi: 08 β Dart 3 zamonaviy imkoniyatlari Β· π README Β· Keyingi: 10 β Flutter bilan tanishuv β‘οΈ
Bu bobda: ba'zi ishlar vaqt talab qiladi β internetdan ma'lumot olish, fayl o'qish, taymer. Agar dastur shu ishni "tik turib" kutsa, ekran muzlab qoladi. Asinxron (asynchronous) dasturlash aynan shu muammoni hal qiladi: kutayotgan paytda dastur boshqa ishlarni qiladi. Bobda Dart'ning bitta oqim + event loop modelini,
Futureni (kelajakda keladigan bitta qiymat),async/awaitni (asinxron kodni go'yo sinxrondek yozish),Future.waitni (parallel kutish),Streamni (vaqt o'tib bir nechta qiymat) va og'ir hisob uchunIsolateni o'rganamiz. Bu bob β Flutter'dan oldin majburiy: Flutter'da har bir tarmoq chaqiruviFuture, har bir real-vaqt oqimiStream.
Muammo: kutish ekranni muzlatadi¶
Tasavvur qiling, ilovangiz serverdan foydalanuvchi ma'lumotini olishi kerak. Bu bir zumda bo'lmaydi β so'rov internetga ketadi, server javob qaytaradi, hammasi yarim soniya, ba'zan ikki soniya davom etadi. Endi savol: shu yarim soniya davomida dastur nima qiladi?
Agar sinxron (synchronous β "tik turib kutish") yozsangiz, dastur shu paytda hech narsa qila olmaydi. U javob kelguncha qotib turadi. Flutter ilovasida bu degani β ekran muzlaydi: foydalanuvchi tugmani bossa javob bo'lmaydi, animatsiya to'xtaydi, ilova "osilgan"dek ko'rinadi. Telefon egasi esa darhol ilovani yopadi.
Buni hayotiy misol bilan tushunaylik. Oshxonaga kirib taom buyurtma berdingiz:
- Sinxron yo'l: taom tayyor bo'lguncha kassa oldida qimirlamasdan turasiz. Boshqa hech narsa qila olmaysiz β qotib turibsiz. 15 daqiqa shunday.
- Asinxron yo'l: buyurtma berasiz, buzzer (chaqiruv tugmasi) olasiz va stolga borib o'tirasiz, telefoningizni ko'rasiz, suhbatlashasiz. Taom tayyor bo'lganda buzzer jiringlaydi β shunda borib olasiz. Kutish davomida erkin edingiz.
Asinxron dasturlash β aynan shu buzzer. Vaqt talab qiladigan ishni boshlab yuborasiz, "tayyor bo'lganda menga xabar ber" deysiz va ayni paytda dastur boshqa ishlarni bemalol bajaraveradi. Ish tugaganda β natija "jiringlab" keladi.
π Diqqat: asinxron tezroq degani emas. Taom baribir 15 daqiqada tayyor bo'ladi. Asinxron β kutish davomida bloklanmaslik, ya'ni boshqa ishlarni qila olish degani.
Dart bitta oqimda ishlaydi: event loop¶
Asinxronlikni tushunish uchun avval Dart qanday kod yurgizishini bilish kerak. Ko'p tillarda parallellik uchun ko'p oqim (thread) ishlatiladi. Dart esa, asosan, bitta oqimda ishlaydi. Unda parallellik qayerda? Javob β event loop (hodisalar sikli).
Event loop'ni shunday tasavvur qiling: bu β to'xtovsiz aylanadigan kichkina ishchi. Uning oldida navbat (queue) turadi β bajarilishi kerak bo'lgan vazifalar ro'yxati. Ishchi navbatdan bitta vazifani oladi, to'liq bajaradi, keyin keyingisiga o'tadi. Vazifa tugamaguncha keyingisiga o'tmaydi.
void main() {
print('1 β boshlandi');
// Bu vazifa "keyinroq" bajarilsin deb navbatga qo'yiladi:
Future(() => print('3 β navbatdagi vazifa'));
print('2 β tugadi');
}
Chiqishi:
E'tibor bering: print('3...') kodda o'rtada turibdi, lekin oxirida chiqdi. Chunki Future(...) ichidagi ish darhol bajarilmadi β u navbatga qo'yildi. Dart avval main funksiyaning hamma sinxron kodini oxirigacha yurgizadi (1, 2), keyingina event loop navbatdagi vazifaga (3) o'tadi.
Endi eng muhim xulosa: Dart bitta oqimda ishlagani uchun, agar siz bitta vazifani uzoq vaqt band qilib tursangiz, butun dastur to'xtaydi. Masalan, quyidagi kod β falokat:
// β YOMON: bu sikl event loop'ni millionlab takror band qiladi.
// U tugamaguncha boshqa hech narsa β hatto tugma bosishi ham β ishlamaydi.
int yigindi = 0;
for (int i = 0; i < 5000000000; i++) {
yigindi += i;
}
Bu og'ir sikl ishlayotganda event loop boshqa hech narsani qabul qila olmaydi β Flutter'da bu ekranning muzlashidir. Saboq: event loop'ni uzoq sinxron ish bilan band qilmang. Vaqt talab qiladigan ish β bu kutish (tarmoq, fayl) yoki og'ir hisob bo'lishi mumkin. Kutishni Future/async bilan, og'ir hisobni esa Isolate bilan hal qilamiz (ikkalasini ham shu bobda ko'ramiz).
π‘ "
awaitnega ekranni muzlatmaydi?" β chunkiawaitevent loop'ni band qilmaydi. U "men kutyapman, sen boshqa vazifalarni bajaraver" deydi. Natija kelganda funksiyaning davomi navbatga qo'yiladi. Aynan shu sirni quyida ochamiz.
Future β kelajakda keladigan qiymat¶
Future (kelajak) β "hozir emas, keyinroq keladigan qiymat" ni anglatadi. U β oshxonadagi buzzer: hozir qo'lingizda taom yo'q, lekin keyin keladigan taomning va'dasi bor.
Future ham generic tip: Future<T> β kelajakda T tipidagi qiymat keladi deganidir.
Future<String>β keyin matn keladi (masalan, foydalanuvchi ismi).Future<int>β keyin son keladi.Future<void>β keyin qiymatsiz ish tugaydi (faqat "bajarildi" signali).
Future ikki yo'l bilan tugaydi: yo muvaffaqiyatli qiymat bilan, yo xato (error) bilan. Bu ham buzzer kabi β taom tayyor bo'lishi yoki "kechirasiz, tugab qoldi" javobi kelishi mumkin.
Eng oson Future yaratish usuli β Future.delayed, ya'ni "shuncha vaqtdan keyin shu qiymatni ber":
// 2 soniyadan keyin matn qaytaradigan Future:
Future<String> salomBer() {
return Future.delayed(
const Duration(seconds: 2),
() => 'Salom, dunyo!',
);
}
salomBer() ni chaqirsangiz, qo'lingizda darhol Future<String> paydo bo'ladi β lekin ichidagi matn hali yo'q (quti hali yopiq). Matnga yetish uchun qutini "ochish" kerak. Ochishning eski usuli β .then().
.then() va .catchError() β eski uslub (qisqacha)¶
async/await paydo bo'lishidan oldin Future natijasini .then() bilan olishardi: "qiymat kelganda, mana shu funksiyani chaqir".
void main() {
salomBer()
.then((matn) => print(matn)) // qiymat kelganda chaqiriladi
.catchError((xato) => print('Xato: $xato')); // xato bo'lsa chaqiriladi
print('Bu birinchi chiqadi β Future hali kutilyapti');
}
Bu ishlaydi, lekin bir nechta Future ketma-ket kerak bo'lsa .then() ichida .then() paydo bo'lib, kod "narvon"ga aylanadi va o'qish qiyinlashadi. Shu sababli zamonaviy Dart'da asosiy usul β async/await. .then() ni faqat eski kodni o'qiy olish uchun bilib qo'ying.
async / await β asosiy usul¶
async/await β asinxron kodni go'yo oddiy sinxron koddek yozish imkonini beradi, lekin u baribir bloklamaydi. Bu β Dart'da asinxronlikning asosiy va eng o'qiladigan usuli.
Ikkita qoida bor, ular bir-birining aksi:
asyncβ funksiyani "asinxron" deb belgilaydi. Bunday funksiya doimFutureqaytaradi: ichidaStringqaytarsangiz, tashqaridan uFuture<String>bo'ladi.awaitβFuturequtisini ochib, ichidagi qiymatni beradi. U faqatasyncfunksiya ichida ishlatiladi.
Future<String> salomBer() {
return Future.delayed(const Duration(seconds: 2), () => 'Salom!');
}
Future<void> main() async { // main ham async bo'ldi
print('Kutyapmiz...');
final matn = await salomBer(); // quti ochilguncha "kutadi" (lekin bloklamaydi)
print(matn); // 2 soniyadan keyin: Salom!
}
await salomBer() qatorida sehrgarlik yashiringan. Tashqaridan bu "2 soniya kutdik, keyin matnga qiymatni oldik" kabi ko'rinadi β xuddi oddiy kod. Lekin ichkarida boshqacha: await event loop'ga "men kutyapman, boshqa vazifalarni yurgizaver" deydi. Natija kelganda funksiyaning davomi (ya'ni print(matn)) navbatga qo'yiladi va yurgiziladi. Shuning uchun ekran muzlamaydi.
Realistik misol: foydalanuvchini "olish"¶
Hayotiy ko'rinishga keltiraylik β serverdan foydalanuvchi ismini olishni Future.delayed bilan taqlid qilamiz (haqiqiy tarmoq chaqiruvini 21-bobda ko'ramiz):
Future<String> foydalanuvchiOl(int id) async {
// Haqiqatda bu yerda tarmoq so'rovi bo'ladi; biz 1 soniya "kutamiz":
await Future.delayed(const Duration(seconds: 1));
if (id <= 0) {
throw Exception('Noto\'g\'ri id: $id'); // xato ham qaytishi mumkin
}
return 'Foydalanuvchi #$id';
}
Future<void> main() async {
print('Yuklanmoqda...');
final ism = await foydalanuvchiOl(7);
print('Keldi: $ism'); // Keldi: Foydalanuvchi #7
}
foydalanuvchiOl async bo'lgani uchun, garchi ichida String qaytarayotgan bo'lsa ham, uning tashqi tipi β Future<String>. Chaqirgan joyda await bilan ochib, oddiy String olamiz.
Xatolarni try / catch bilan ushlash¶
async/await ning eng katta qulayligi: xatolarni oddiy try/catch bilan ushlaysiz β xuddi sinxron koddagidek. .catchError() kerak emas.
Future<void> main() async {
try {
final ism = await foydalanuvchiOl(-1); // id noto'g'ri -> xato otadi
print('Keldi: $ism');
} catch (xato) {
print('Muammo yuz berdi: $xato'); // Muammo yuz berdi: Exception: Noto'g'ri id: -1
} finally {
print('Yuklash tugadi (muvaffaqiyat yoki xato β bari bir).');
}
}
Agar await foydalanuvchiOl(-1) ichida xato otsa, u try blokidan "sakrab" catchga tushadi β xuddi oddiy istisno (exception) kabi. finally esa har holatda ishlaydi. Bu β 08-bobda ko'rgan try/catchning aynan o'zi, lekin endi asinxron kod uchun. Xatoni hech qachon e'tiborsiz qoldirmang: tarmoq uzilishi, server xatosi β bular doim bo'lib turadi, ularni ushlash shart.
Ketma-ket va parallel: Future.wait¶
Aytaylik, sizga uchta narsa kerak: foydalanuvchi, uning buyurtmalari va sozlamalari. Har biri 1 soniya "oladi". Ularni qanday olamiz?
Ketma-ket (sequential) β birini kutib, keyin ikkinchisini, keyin uchinchisini:
Future<void> ketmaKet() async {
final a = await foydalanuvchiOl(1); // 1 soniya
final b = await foydalanuvchiOl(2); // yana 1 soniya
final c = await foydalanuvchiOl(3); // yana 1 soniya
print('$a, $b, $c'); // jami: ~3 soniya
}
Bu 3 soniya oladi β chunki har bir await oldingisi tugaguncha kutadi. Lekin bu uchta so'rov bir-biriga bog'liq emas-ku! Ularni bir vaqtda boshlasak bo'ladi. Buning uchun Future.wait bor β u bir nechta Futureni parallel kutadi va hammasi tayyor bo'lganda ro'yxat qaytaradi:
Future<void> parallel() async {
final natijalar = await Future.wait([
foydalanuvchiOl(1),
foydalanuvchiOl(2),
foydalanuvchiOl(3),
]);
print(natijalar); // [Foydalanuvchi #1, #2, #3] β jami: ~1 soniya!
}
Endi jami atigi ~1 soniya, chunki uchovi bir vaqtda yurdi. Qoida oddiy: agar so'rovlar bir-biriga bog'liq bo'lmasa (biri ikkinchisining natijasini kutmasa), Future.wait bilan parallel qiling. Agar biri ikkinchisining natijasiga bog'liq bo'lsa (masalan, avval foydalanuvchini olib, keyin uning id'si bilan buyurtmalarini olish) β u holda ketma-ket await kerak.
β οΈ
Future.waitda bittaFuturexato otsa, butunFuture.waitxato otadi. Har bir natijani alohida ushlamoqchi bo'lsangiz,eagerError: falseyoki har birFuturega o'z.catchErrorini biriktirish kerak. Hozircha esa: bog'liqmas ishlarni parallel qilish β eng tez-tez kerak bo'ladigan optimizatsiya.
Stream β vaqt o'tib keladigan bir nechta qiymat¶
Future β bitta qiymat (bitta buzzer jiringlashi). Lekin ba'zida bizga ketma-ket, vaqt o'tib keladigan ko'p qiymat kerak: har soniyada bir marta jiringlaydigan taymer, har bir tugma bosilishi, serverdan oqib keladigan xabarlar. Buni Stream (oqim) ifodalaydi.
Farqni shunday yodda saqlang:
Future<T>β kelajakda bittaTkeladi, keyin tugaydi. (Bitta posilka.)Stream<T>β vaqt o'tib ko'pTkeladi: 1, 2, 3, ... keyin oqim yopiladi. (Quvur orqali oqib keladigan ko'p posilka.)
Stream yaratish: async* va yield¶
O'z Streamingizni async* (yulduzcha bilan!) funksiya orqali yaratasiz. Unda return o'rniga yield ishlatiladi β yield "mana, oqimga yana bitta qiymat chiqaraman, lekin funksiya davom etaveradi" deganidir.
// Har soniyada bir marta 1, 2, 3 chiqaradigan taymer-oqim:
Stream<int> sanagich(int oxiri) async* {
for (int i = 1; i <= oxiri; i++) {
await Future.delayed(const Duration(seconds: 1));
yield i; // oqimga i ni chiqaradi (return EMAS β davom etadi)
}
}
Streamni tinglash: await for va .listen()¶
Oqimdan keladigan qiymatlarni ikki yo'l bilan "tinglash" mumkin. Birinchisi β await for, oddiy for kabi, lekin har bir qiymat kelgan sayin tanani yurgizadi:
Future<void> main() async {
await for (final son in sanagich(3)) {
print('Keldi: $son'); // har soniyada: Keldi: 1 / 2 / 3
}
print('Oqim tugadi.');
}
Ikkinchisi β .listen(), u callback ro'yxatdan o'tkazadi va await qilmasdan davom etadi (Flutter'da ko'p ishlatiladi):
void main() {
sanagich(3).listen(
(son) => print('Qiymat: $son'), // har qiymatda
onError: (xato) => print('Xato: $xato'), // xato bo'lsa
onDone: () => print('Oqim yopildi'), // oqim tugaganda
);
}
Single-subscription va broadcast (qisqacha)¶
Streamning ikki turi bor. Standart Stream β single-subscription (bitta obunachi): uni faqat bitta marta tinglash mumkin, ikkinchi .listen() xato beradi. Bu β fayl o'qish kabi "boshidan oxirigacha bir marta" oqadigan ma'lumotlar uchun. Broadcast oqim esa ko'p tinglovchiga ruxsat beradi (.asBroadcastStream() yoki StreamController.broadcast()) β masalan, bir nechta widget bir hodisani kuzatishi kerak bo'lganda. Hozircha shu farqni bilib qo'ying; tafsilotlarni 23-bobda ko'ramiz.
Flutterga ko'prik: FutureBuilder va StreamBuilder¶
Nega bu bob Flutter'dan oldin kerak? Chunki Flutter'da asinxron ma'lumotni ekranga chizish to'g'ridan-to'g'ri shu tushunchalarga tayanadi:
- Har bir tarmoq (API) chaqiruvi
Futureqaytaradi. Foydalanuvchi profili, mahsulotlar ro'yxati, ob-havo β bularning hammasiFuture. Flutter ularni ekranga aylantirish uchunFutureBuilderwidgetini beradi: uFutureni kuzatadi va "yuklanmoqda β tayyor β xato" holatlariga qarab UI chizadi. - Real-vaqt ma'lumot
Streambilan keladi: chat xabarlari, jonli narx, GPS joylashuv. BuniStreamBuilderwidgeti ekranga chizadi.
Hozircha bularni faqat tishlab ko'rish uchun aytdik β kodini keyin yozamiz. Muhimi shu: agar Future va Streamni hozir tushunmasangiz, Flutter'dagi ma'lumotli ekranlar siz uchun "sehr" bo'lib qolaveradi. Shuning uchun bu bob β poydevor.
π Tarmoq va
FutureBuilderβ 21-bob: Tarmoq (networking) va API.StreamvaStreamBuilderbilan reaktiv UI β 23-bob: Stream va reaktiv UI.
Isolate β og'ir hisob uchun haqiqiy parallellik (qisqacha, ilg'or)¶
Yuqorida aytdik: await kutishni bloklamaydi. Lekin og'ir hisob-chi? Masalan, 50 MB lik JSON faylni tahlil qilish yoki rasmni qayta ishlash β bu kutish emas, bu protsessorning haqiqiy ishi. Bunday ishni async qilsangiz ham, u baribir bitta oqimda ishlaydi va event loop'ni band qiladi β ekran muzlaydi.
Mana shu yerda Isolate kerak. Isolate β Dart'dagi haqiqiy parallellik: alohida oqim, alohida xotira bilan. "Isolate" so'zi "ajratilgan" degani β u boshqa isolate xotirasini ko'ra olmaydi, ular faqat xabar orqali gaplashadi (postcard yuborish kabi). Shuning uchun bir isolate og'ir hisob qilsa, asosiy isolate (UI) bemalol ishlayveradi.
Eng oson yo'li β Isolate.run (Dart 3): og'ir funksiyani alohida isolate'da yurgizib, natijasini await qiladi:
// Og'ir, protsessorni band qiladigan hisob (taqlid):
int ogirHisob(int n) {
int yigindi = 0;
for (int i = 0; i < n; i++) {
yigindi += i;
}
return yigindi;
}
Future<void> main() async {
// Bu hisob ALOHIDA isolate'da yuradi β UI (asosiy isolate) muzlamaydi:
final natija = await Isolate.run(() => ogirHisob(1000000000));
print('Natija: $natija');
}
Isolate.run og'ir ishni boshqa isolate'ga "uloqtiradi", asosiy oqim esa erkin qoladi va natija tayyor bo'lganda await orqali oladi. Qachon kerak? Faqat og'ir, uzoq hisob uchun: katta JSON tahlili, rasm/video qayta ishlash, kriptografiya, murakkab algoritmlar. Oddiy tarmoq kutishi uchun isolate kerak EMAS β uni async/await o'zi muammosiz hal qiladi. Isolate β kam, lekin muhim hollarda ishlatiladigan kuchli vosita.
Eng ko'p uchraydigan xatolar¶
awaitni unutish.final ism = foydalanuvchiOl(7);(awaitsiz) yozsangiz,ismga qiymat emas,Future<String>obyekti tushadi. Keyinism.toUpperCase()qilolmaysiz β chunki u hali quti. Qoida:asyncfunksiya natijasini ishlatishdan oldin deyarli doimawaitqiling.- Event loop'ni og'ir sinxron sikl bilan bloklash. Millionlab takrorli
foryoki katta hisob β ekranni muzlatadi. Yechim: og'ir hisobniIsolate.runga bering. - Xatoni ushlamaslik. Tarmoq uziladi, server xato beradi β bu muqarrar.
awaitnitry/catchga o'rang yoki.catchErrorqo'ying. Aks holda ilova kutilmaganda yiqiladi. asyncqo'yib,Futureqaytarishni unutish. Funksiyaniasyncqilsangiz, uning tipi avtomatikFuture<...>bo'ladi β buni chaqirgan joyda hamawaitqilishni unutmang.- Single-subscription stream'ni ikki marta tinglash. Oddiy
Streamni ikkinchi marta.listen()qilsangiz xato beradi β bunday holat uchun broadcast oqim kerak.
Xulosa¶
- Nega asinxron: ba'zi ishlar vaqt oladi (tarmoq, fayl, taymer). Sinxron kutsangiz ekran muzlaydi. Asinxron β kutish davomida bloklanmaslik (oshxona buzzer'i).
- Event loop: Dart bitta oqimda ishlaydi; navbatdagi vazifalarni birma-bir yurgizadi. Uzoq sinxron ish β hammasini to'xtatadi.
Future<T>β kelajakda keladigan bitta qiymat (yoki xato).Future.delayedyokiasyncfunksiya yaratadi. Eski uslub β.then()/.catchError().async/awaitβ asosiy usul.asyncqiymatniFuturega o'raydi;awaitqutini ochib qiymatni beradi va event loop'ni bloklamaydi. Xatolar β oddiytry/catch.Future.waitβ bog'liqmas so'rovlarni parallel kutadi (3 soniya β 1 soniya). Bog'liq bo'lsa β ketma-ketawait.Stream<T>β vaqt o'tib keladigan ko'p qiymat.async*+yieldyaratadi;await foryoki.listen()tinglaydi. Single-subscription vs broadcast.- Flutter ko'prigi: har API chaqiruvi
Future(βFutureBuilder), real-vaqt βStream(βStreamBuilder). Isolateβ og'ir hisob uchun haqiqiy parallellik (alohida xotira, xabar almashish).Isolate.run. Oddiy kutish uchun kerak emas.
Mashqlar¶
π‘ Mashqlarni alohida
.dartfaylda yozib,dart runbilan ishga tushiring. Asinxron natijalar tartibiga (qaysi
-
Tartibni bashorat qiling. Quyidagi kod nima chiqaradi va qaysi tartibda? Avval o'zingiz bashorat qiling, keyin ishga tushirib tekshiring.
-
Future.delayed.intqaytaradigantasodifiySon()funksiyasini yozing: 2 soniyadan keyin42qaytarsin (Future.delayedbilan).mainda uniawaitqilib chop eting. Qaytish tipini aniq (Future<int>) yozing. -
try/catchbilan xato.bolish(int a, int b)asyncfunksiyasini yozing:b == 0bo'lsaExceptionotsin, aks holdaa ~/ bqaytarsin.mainda uni0ga bo'lib ko'ring va xatonitry/catchbilan ushlab, tushunarli xabar chiqaring. -
Ketma-ket vs parallel. Har biri 1 soniya
Future.delayedqiladigan uchta funksiyani (a) ketma-ketawaitbilan, (b)Future.waitbilan chaqiring. Har ikki holat uchunStopwatchbilan vaqtni o'lchang va farqni izohlang. -
Streamyaratish.async*vayieldbilanteskariSanagich(int n)oqimini yozing:ndan 1 gacha, har yarim soniyada bittadan qiymat chiqarsin.await forbilan tinglab, har bir qiymatni chop eting. -
awaitni unutish tuzog'i. 2-mashqdagitasodifiySon()niawaitsiz chaqirib (final x = tasodifiySon();),xni chop eting. Nima chiqadi va nega? So'ngawaitqo'shib to'g'rilang.
Yechim β 1
Chiqishi:
A va C β sinxron kod, shuning uchun darhol, tartib bilan chiqadi. Future(() => print('B')) esa ishni navbatga qo'yadi; event loop maindagi hamma sinxron kod (A, C) tugagandan keyin navbatdan Bni oladi. Kodda B o'rtada bo'lsa-da, u oxirida chiqadi β event loop modelining asosiy isboti.
Yechim β 2
Future<int> tasodifiySon() {
return Future.delayed(const Duration(seconds: 2), () => 42);
}
Future<void> main() async {
print('Kutyapmiz...');
final son = await tasodifiySon();
print('Keldi: $son'); // 2 soniyadan keyin: Keldi: 42
}
tasodifiySon() chaqirilganda darhol Future<int> qaytadi; await 2 soniya kutadi (lekin bloklamaydi) va ichidagi 42ni beradi.
Yechim β 3
Future<int> bolish(int a, int b) async {
if (b == 0) {
throw Exception('Nolga bo\'lib bo\'lmaydi');
}
return a ~/ b;
}
Future<void> main() async {
try {
final natija = await bolish(10, 0);
print('Natija: $natija');
} catch (xato) {
print('Xato ushlandi: $xato'); // Xato ushlandi: Exception: Nolga bo'lib bo'lmaydi
}
}
await bolish(10, 0) ichida xato otganda u catchga "sakraydi" β xuddi sinxron try/catchdagidek. Asinxron kodda ham xatoni shunday tabiiy ushlaymiz.
Yechim β 4
Future<int> ish(int n) => Future.delayed(const Duration(seconds: 1), () => n);
Future<void> main() async {
// (a) Ketma-ket β ~3 soniya
final s1 = Stopwatch()..start();
await ish(1);
await ish(2);
await ish(3);
print('Ketma-ket: ${s1.elapsed.inMilliseconds} ms');
// (b) Parallel β ~1 soniya
final s2 = Stopwatch()..start();
await Future.wait([ish(1), ish(2), ish(3)]);
print('Parallel: ${s2.elapsed.inMilliseconds} ms');
}
Ketma-ketda har await oldingisi tugaguncha kutadi β vaqtlar qo'shiladi (~3000 ms). Future.waitda uchovi bir vaqtda boshlanadi β eng uzuni qancha bo'lsa, jami shuncha (~1000 ms). Bog'liqmas ishlar uchun parallel doim tezroq.
Yechim β 5
Stream<int> teskariSanagich(int n) async* {
for (int i = n; i >= 1; i--) {
await Future.delayed(const Duration(milliseconds: 500));
yield i;
}
}
Future<void> main() async {
await for (final son in teskariSanagich(5)) {
print('Qiymat: $son'); // har 0.5 soniyada: 5, 4, 3, 2, 1
}
print('Tugadi!');
}
async* funksiya Stream qaytaradi; har yield oqimga bitta qiymat chiqaradi, lekin funksiya davom etadi. await for har qiymat kelgan sayin tanani yurgizadi.
Yechim β 6
Future<void> main() async {
final x = tasodifiySon(); // β await yo'q
print(x); // Instance of 'Future<int>' <- son emas, QUTI!
final y = await tasodifiySon(); // β
to'g'ri
print(y); // 42
}
awaitsiz x β bu Future<int> obyektining o'zi (yopiq quti), shuning uchun print(x) Instance of 'Future<int>' chiqaradi, 42 emas. await qutini ochib, ichidagi 42ni beradi. Bu β eng ko'p uchraydigan boshlovchi xatosi.
β¬ οΈ Oldingi: 08 β Dart 3 zamonaviy imkoniyatlari Β· π README Β· Keyingi: 10 β Flutter bilan tanishuv β‘οΈ