Dart Asinxronizatsiyaga kirish va Future

Dart dasturlash tili ko’pgina zamonaviy dasturlash tillari kabi, asinxronizatsiyaga ega. Nega asinxronizatsiya kerak? Masalan, Android-dagi grafik ilovani olaylik. Android-da ilovani ishga tushirganingizda, u asosiy foydalanuvchi interfeysida ishlaydi. Ushbu asosiy mavzu tugmani bosish, ekranga teginish va boshqalar kabi barcha UI hodisalarini boshqaradi. Biz tugmachalarni bosishimiz, matn maydonlariga matn kiritishimiz mumkin va asosiy mavzu hamma narsani qayta ishlaydi. Biroq, ilovalarning ishi, qoida tariqasida, bu bilan cheklanmaydi. Misol uchun, elektron pochta ilovasi bir vaqtning o'zida tarmoq bo'ylab so'rovlarni yuborishi mumkin - avval yozilgan elektron pochta xabarlarini yuborish yoki yangi elektron pochta xabarlarini tekshirish uchun server bilan bog'lanish. Tarmoq so'rovi, ayniqsa, beqaror Internet sharoitida ko'p vaqt talab qilishi mumkin. Biroq, bunday tarmoq so'rovlari odatda asosiy UI oqimini bloklamaydigan tarzda yuboriladi. Agar tarmoq so'rovlari asosiy oqimda qilingan bo'lsa, u holda foydalanuvchi tarmoq so'rovi yuborilishini va uning natijasini olishini kutishi kerak edi va so'rov davomida dastur bloklanadi va so'rovning tugashini kutadi. Biroq, ko'pgina oddiy ilovalarda bu sodir bo'lmaydi - biz xat yuborishimiz va dastur qotib qolmagan holda darhol yangi xat yozishni boshlashimiz mumkin - chunki tarmoq so'rovi asinxron tarzda amalga oshiriladi. Va u tugallanganda, biz shunchaki bildirishnomani ko'rishimiz mumkin. Bu asinxronizatsiyadan foydalanishning afzalligi. Bundan tashqari, bu nafaqat tarmoq so'rovlariga, balki umuman dasturning uzoq vaqt talab qilishi mumkin bo'lgan barcha og'ir vazifalariga ham tegishli.

Dart dasturlash tilining o'ziga kelsak, u bir oqimli tildir - u bir vaqtning o'zida faqat bitta vazifani bajarishi mumkin. Biroq, jarayonlar siklini va ikkita jarayon navbatini (event queue va microtask queue) amalga oshirish tufayli u turli xil vazifalarni asinxron ravishda bajarishga imkon beradi. MicroTask queue kichik ichki vazifalarni - mikrotask larni saqlash uchun mo'ljallangan va asosan Dart tomonidan ichki holatda ishlatiladi.

Vazifalarning asosiy qismi event queue ga joylashtiriladi - bular tashqi hodisalar, masalan, GUI hodisalari (masalan, grafik ilovalardagi tugmani bosish), taymerlar, fayllarni o'qish va yozish, tashqi tarmoq resurslaridan ma'lumotlarni qabul qilish va boshqalar.

Har qanday Dart ilovasi ishga tushirilganda, bitta dastur zanjiri ishlay boshlaydi. Yagona Dart oqimi izolyatsiya deb ataladigan narsa ichida ishlaydi . Har bir izolyatsiya o'ziga xos xotira maydoniga ega, bu esa boshqa hech qanday izolyatsiya joriy izolyatsiya holatiga kira olmasligini ta'minlaydi. Bu murakkab qulflash va resurslarga kirishni boshqarish tizimlariga ehtiyoj yo'qligini va nozik ma'lumotlarning ancha xavfsiz ekanligini anglatadi. |

Bitta dastur zanjiri ikkita navbatni ishga tushiradi - MicroTask va Event - ular bajarilishi kerak bo'lgan vazifalarni o'z ichiga oladi. Keyinchalik, oqim main() funksiyasini ishga tushiradi va birinchi navbatda undagi barcha sinxron vazifalarni bajaradi. Sinxron vazifalar har doim darhol bajariladi. Agar Dart kechiktirilishi mumkin bo'lgan uzoq muddatli vazifaga duch kelsa, u event queue ga joylashtiriladi .

Dart sinxron vazifalarni bajarishni tugatgandan so'ng, jarayonlar davri microtask queue ni tekshiradi. Agar bu navbatda biror-bir vazifa bo'lsa, jarayon sikli ularni keyinchalik bajarish uchun asosiy oqimga joylashtiradi.

Sinxron topshiriqlar va microtask queue topshiriqlari bajarilishini tugatgandan so'ng, event queue dagi vazifalarni tanlay boshlaydi va ularni sinxron ravishda bajariladigan asosiy oqimga joylashtiradi.

Agar microtask queue ga yangi mikrovazifa kelib tushsa, jarayon sikli uni event queue dan keyingi har qanday vazifadan oldin bajaradi. Bu jarayon navbatlar bo'sh qolguncha davom etadi.

Future sinfi

Asinxron vazifalarni aniqlash uchun asosiy sinf Future sinfidir. Future sinfi kelajakda bajarilishini yakunlaydigan ya’ni kutilayotgan operatsiya natijasini belgilaydi. Future sinfi orqali yaratilgan obyekt 2 ta holatda bo’lishi mumkin: tugallangan va tugallanmagan.

  • Tugallanmagan holatda – Future obyekti ko’rsatadigan operatsiya bajarila boshlangan bo’lishi mumkin, ammo natija hali olinmagan.
  • Tugallangan holatda – operatsiya allaqachon bajarilishini tugatgan, uning natijasi sifatida ma’lum bir qiymat yoki xato olingan bo’ladi.

Endi misolni ko’rib chiqaylik:

Future xabar() {
return Future.delayed(Duration(seconds: 4), () => print("Uzbekdevsdan yangi xabar keldi"));
}

void main() {
xabar();
print('Xabarlar tekshirilmoqda...');
}
>> Xabarlar tekshirilmoqda... >> Uzbekdevsdan yangi xabar keldi

Bu yerda Future obyekti qaytaradigan xabar funksiyasi mavjud. Bu funksiya Future sinfining nomli konstruktorlaridan birini chaqiradi – Future.delayed(). Ushbu konstruktor ikkita parametrni oladi. Birinchi parametr Duration obyekti bo'lib, Duration(seconds: 4) bu holda kechikish vaqtini to’rt soniyaga o'rnatadi. Ikkinchi parametr - bu ba'zi amallarni bajaradigan funksiya - bu holda u shunchaki ekranga xabarni chop etadi.

() => print("Uzbekdevsdan yangi xabar keldi")

Shunday qilib, to’rt soniyadan so'ng ekranda "Uzbekdevsdan yangi xabar keldi" qatori paydo bo'ladi. Bu, asosan, Future obyekti ifodalovchi kechiktirilgan operatsiyadir.

Asosiy funksiyada biz xabar funksiyasini chaqiramiz va keyin ba'zi xabarlarni chop etamiz. E'tibor bering, xabar funksiyasi birinchi bo'lib chaqiriladi. Biroq, dasturning ekranga chiqishi quyidagicha bo'ladi:

Xabarlar tekshirilmoqda... Uzbekdevsdan yangi xabar keldi

Aslida, xabar funksiyasi asosiy funksiyadagi barcha boshqa amallar bajarilgandan keyingina yakunlanishini ko‘ramiz. Ya'ni, bajarilishi uchun 4 soniya vaqt ketadigan xabar funksiyasi asinxron tarzda bajariladi. Chaqirilsa, xabar funksiyasi tugallanmagan holatda bo'lgan Future obyektini qaytaradi. Va konstruktordan funksiyani bajargandan so'ng atigi to’rt soniyadan so'ng Future.delayed tugallangan holatga o'tadi.

Future ning ishlash usuli shundan iboratki, yangi Future obyekti aniqlanganda u ifodalovchi operatsiya (masalan, bu holda xabarni qabul qilish) jarayon navbatiga o‘tadi. Keyin, jarayonlar siklida asosiy funksiya bajarilgandan so'ng, bu operatsiya jarayonlar navbatidan olinadi va bajariladi.

Future obyektini yaratish uchun siz uning konstruktorlaridan birini ishlatishingiz mumkin:

  • Future(FutureOr<T> computation()): Timer.run usuli yordamida hisoblash funksiyasini asinxron tarzda boshqaradigan va uning natijasini qaytaradigan Future obyektini yaratadi.
  • Tur FutureOr<T> funksiyasi Future<T> yoki T tipidagi obyektni qaytarishi kerakligini bildiradi.
  • Future.delayed(Duration duration, [FutureOr<T> computation()]): Birinchi Duration parametri orqali belgilangan vaqt kechikishidan keyin ishlaydigan Future obyektini yaratadi. Ikkinchi ixtiyoriy parametr bu kechikishdan keyin bajariladigan funksiyani belgilaydi.
  • Future.error(Object error, [StackTrace stackTrace]): sodir bo'lgan xato haqida ma'lumotni o'z ichiga olgan Future obyektini yaratadi.
  • Future.microtask(FutureOr<T> computation()): scheduleMicrotask funksiyasidan foydalanib, hisoblash funksiyasini asinxron tarzda ishga tushiradigan va uning natijasini qaytaradigan Future obyektini yaratadi.
  • Future.sync(FutureOr<T> computation()): Darhol chaqiriladigan hisoblash funksiyasi natijasini o'z ichiga olgan Future obyektini yaratadi.
  • Future.value([FutureOr<T> value]): qiymatni o'z ichiga olgan Future obyektini yaratadi.