Adnan Kamali | عدنان کمالی
خواندن ۳ دقیقه·۲۴ روز پیش

برنامه نویسی ناهمزمان در دارت

برنامه نویسی ناهمزمان در فلاتر
برنامه نویسی ناهمزمان در فلاتر

توی فلاتر یه زمان هایی هست که میخوایم دیتایی رو از سرور دریافت کنیم یا دیتایی رو توی دیتابیس بنویسیم یا حتی دیتایی رو از فایلی بخونیم اگر بصورت همزمان یا Synchronous انجام بدیم باعث میشه که برنامه ما فریز بشه و تا زمانی که این عملیات انجام نشده کاربر ما هر حرکتی روی اپلیکیشن بزنه انگار نه انگار برنامه کار میکنه و اگر این عملیات طول بکشه کاربر حتی فکر میکنه که برنامه ما هنگ کرده و فوش و الی آخر

برنامه نویسی ناهمزمان کلید موفقیت

برای اینکه بتونیم از دعوا و مرافعه دوری کنیم میایم از برنامه نویسی ناهمزمان یا Asynchronous استفاده میکنیم، حالا چطوری؟

برای استفاده از برنامه نویسی ناهمزمان در دارت ما از این کلمات کلیدی استفاده میکنیم:

  • Future
  • Stream
  • async (or async* for Stream)
  • await
  • yield (or yield*) use in Stream

نتیجه های محاسبات ناهمزمان معمولا بصورت Future است یعنی خروجی Future به ما می دهد و اگر نتیجه های ما چند بخشی باشد مثل صفحه بندی (Pagination) که باید درخواست صفحه بعد داد رو با Stream پیاده سازی میکنیم

  • یه نکته رو بگم ما در این بخش از Future استفاده میکنیم و در آینده برای Stream نوشته خواهم داشت

چیه Future

یک Future در واقع نشان دهنده عملیات ناهمزمانه که دو حالت براش هست

  1. تکمیل نشده

در این وضعیت زمانی که شما یک فانکنش ناهمزمان (Future) را فراخوانی می کنید، همون موقع یک Future تکمیل نشده به شما بر میگردونه که درحال پروسه انجام، حالا ممکنه این پروسه تکمیل بشه یا ارور برگشت داده بشه

2. تکمیل شده

در این وضعیت عملیات موفقیت آمیز بوده و Future ما تکمیل شده به همراه مقدار و یا ممکنه تکمیل شده همراه با ارور

این فیوچر ها میتونن مقدار بگیرن مثل String یا هر تایپی که تعریف کرده باشیم که به شکل <Future<T که T همون تایپ مقدار ما هستن که برای رشته میشه <Future<String

برای مثال

Future<void> fetchUserOrder() {

// فکر کنید این تابع از دیتابیس دیتایی رو میگیره و به مدت 2 ثانیه طول میکشه.

return Future.delayed(const Duration(seconds: 2), () => print('Got it From Database'));

}


void main() {

fetchUserOrder();

print('Fetching user order from database...');

}

ما از زمانی که فانکشن ناهمزمان خودمون رو یعنی fetchUserOrder رو فراخوانی میکنیم بعد از دو ثانیه تاخیر که بصورت فیک با Future.delayed بهش دادیم مقدار Got it From Database رو برامون پرینت میکنه و براش فرقی نداره که چه کد هایی بعدش هست.

خب پس خروجی نهایی کد میشه

Fetching user order from database...

Got it From Database // مشاهده بعد از دو ثانیه


استفاده از async, await

کلمات کلیدی async و await برای ما این امکان رو فراهم میکنه که توی فانکشن های ناهمزمان استفاده کنیم و از مقدار نهایی آنها بهره مند شیم که دوتا نکته داره

  1. استفاده از async قبل از بدنه فانکشن ناهمزمان استفاده میشه
  2. کلمه کلیدی await باید در فانکشنی استفاده بشه که دارای async است و گرنه بدون اون کار نمیکنه

برای اینکار در مرحله اول فانکشن main رو تبدیل به فیوچر میکنیم و کلمه کلیدی async رو قبل از بدنه اضافه

و در کد زیر فانکشن countSecond میاد بصورت ناهمزمان ثانیه هارو میشماره که تا 6 ثانیه هست

فانکشن getOrderMessage داریم که با چهار ثانیه تاخیر مقدار "Order message" بر میگردونه

یه نکته رو بگم که کلید واژه await به معنی صبر کردن هست و این کلمه کلیدی میاد بعد از صبر مقدار رو برمیگردونه

خب میایم میگیم که برای فانکشن getOrderMessage صبر کن تا مقدار واقعیش رو بربگردونه و بعد مقدار رو پرینت کن

حالا اگر کد رو اجرا کنیم ...

Future<void> main() async {

countSeconds(6);

final result = await getOrderMessage();

print(result);

}

Future<String> getOrderMessage() async {

await Future.delayed(Duration(seconds: 4));

return "Order message";

}

void countSeconds(int s) {

for (var i = 1; i <= s; i++) {

Future.delayed(Duration(seconds: i), () => print(i));

}

}

نتیجه رو به شکل زیر میبینیم که بعد از ثانیه 4 مقدار Order message چاپ میشه

result:

1

2

3

4

Order message

5

6

امیدوارم تونسته باشم مفهوم فیوچر رو جا انداخته باشم

منبع من برای این نوشته وبسایت pub.dev هست

برنامه نویس فلاتر و درحال تبدیل شدن به مهندس نرم افزار
شاید از این پست‌ها خوشتان بیاید