با عرض سلام خدمت کاربران محترم سایت پی وی لرن.
با جلسه ای دیگر از سری جلسات دوره آموزش زبان برنامه نویسی دارت Dart در خدمت شما هستیم.
در این جلسه قصد داریم به آموزش برنامه نویسی غیر همزمان (Asynchronous) در زبان دارت Dart بپردازیم.
مفهوم برنامه نویسی غیر همزمان ممکن است کمی گیج کننده به نظر برسد اما کار با آن بسیار ساده است.
برنامه نویسی غیر همزمان مفهومی است که در آن دستورات یا کد های asynchronous به صورت مستقل از سایر دستورات اجرا میشود.
در حالت عادی دستورات پشت سر هم اجرا میشوند و تا زمانی که اجرای یک دستور به پایان نرسیده است، دستورات بعدی اجرا نمیشوند.
اما هنگامی که یک دستور asynchronous اجرا میشود، سایر دستورات برنامه به اجرای خود بدون توجه به این نوع دستورات ادامه میدهند.
مثال زیر را در نظر بگیرید:
1 2 3 4 5 6 7 8 9 | import 'dart:io'; void main() { print("Enter your name :"); String name = stdin.readLineSync(); print("Hello Mr. ${name}"); print("End of main"); } |
()readLineSync یک تابع synchronus (همزمان) است. (مانند تابع print)
یعنی تمام دستوراتی که به دنبال این تابع آمده اند، تا زمانی که اجرای این تابع به پایان نرسد، اجرا نخواهد شد.
این تابع منتظر ورودی کاربر میماند و زمانی که کاربر آن را وارد کرد، این تابع مقدار آن ورودی را برمیگرداند.
خروجی مثال بالا به شکل زیر است:
1 2 3 4 5 | Enter your name : Tom Hello Mr. Tom End of main |
مشکل برنامه نویسی همزمان یا synchronous در این است که اگر اجرای یک تابع مدت زیادی طول بکشد، سایر کد های برنامه منتظر اجرا میمانند.
برای رفع این مشکل از تکنیک برنامه نویسی غیر همزمان یا Asynchronous استفاده میکنیم.
در این روش میتوانیم یک تابع را را به صورت async تعریف و اجرا کرده و همزمان، سایر کد های برنامه که به دنبال آن تابع آمده اند نیز میتوانند اجرا شوند. (نمیدونم چرا اسم این روش رو گذاشتن غیر همزمان!)
به نظر میرسد در برنامه نویسی غیر همرمان نیز یک مشکل وجود دارد.
فرض کنید برنامه ای نوشته اید یک یک عکس را از اینترنت دریافت کرده و آن را نمایش میدهد.
از آن جایی که تابع دریافت تصویر از اینترنت را به صورت async پیاده سازی کرده ایم، سایر کد های برنامه نیز همزمان با اجرای این تابع، اجرا خواهد شد.
یعنی تابع مربوط به نمایش تصویر نیز اجرا خواهد شد اما به درستی کار نخواهد کرد زیرا تصویر هنوز به صورت کامل دریافت نشده است.
در اینجا احساس میشود که تابع نمایش تصویر باید پس از اجرای کامل تابع دریافت تصویر (async) اجرا شود.
برای این مشکل راه حل ساده ای وجود دارد.
باید کاری کنیم که تابع async مثل synchronous عمل کند.
برای این کار دو روش وجود دارد:
کد هایی که از async و await استفاده میکنند، به صورت غیر همزمان اجرا میشوند.
await حتما باید در یک تابع async اجرا شود.
استفاده از await با یک تابع باعث میشود تا سایر کد ها تا زمانی که اجرای آن تابع تمام نشده است، اجرا نشوند.
در مثال زیر، تا زمانی که اجرای تابع ()lookUpVersion به صورت کامل تمام نشده است، سایر کدهای تابع ()checkVersion (در اینجا تابع print) اجرا نخواهد شد.
1 2 3 4 | Future checkVersion() async { var version = await lookUpVersion(); print("version checked"); } |
Future یک کلاس در کتابخانه dart:async است. از این کلاس برای دریافت مقدار برگشتی یک تابع async استفاده میکنیم.(در مثال بالا هیچ مقداری برگشت داده نمیشود)
همچنین وجود کلاس Future برای استفاده از تابع ()then ضروری است که در ادامه به توضیح آن میپردازیم.
از await میتوانیم چندین بار در یک تابع async استفاده کنیم:
1 2 3 | var entrypoint = await findEntrypoint(); var exitCode = await runExecutable(entrypoint, args); await flushThenExit(exitCode); |
حال مثال کلی زیر را درنظر بگیرید:
1 2 3 4 5 6 7 8 9 10 11 12 | import "dart:async"; import "dart:io"; void main(){ checkVersion(); // once version is checked, call back method is invoked print("End of main"); // this get printed first, showing fileReading is non blocking or async } |
خروجی آن به شکل زیر است:
1 2 | End of main version checked |
متد then از طریق یک تابع که یک مقدار Future را برمیگرداند، فراخوانی میشود.
این متد یک تابع را به عنوان پارامتر گرفته و آن تابع را پس از اجرای کامل تابعی که آن را فراخوانی کرده است، اجرا میکند.
تعدادی از توابع زبان دارت یک مقدار Future برمیگردانند. پس میتوان از متد then بر روی این توابع استفاده کرد.
مانند تابع ()HttpRequest.getString .
نکته: تابعی که یک مقدار Future برمیگرداند، به صورت Async یا غیر همزمان اجرا میشود.
مثال:
فرض کنید فایلی به نام context.txt با محتویات زیر داریم:
1 2 3 4 | 1, Tom 2, John 3, Tim 4, Jane |
برنامه زیر محتویات این فایل را خوانده و آن ها را نمایش میدهد.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import "dart:async"; import "dart:io"; void main(){ File file = new File( Directory.current.path+"\\data\\contact.txt"); Future<String> f = file.readAsString(); // returns a futrue, this is Async method f.then((data)=>print(data)); // once file is read , call back method is invoked print("End of main"); // this get printed first, showing fileReading is non blocking or async } |
خروجی:
1 2 3 4 5 | End of main 1, Tom 2, John 3, Tim 4, Jan |
جلسه آموزش برنامه نویسی غیر همزمان (Asynchronous) در زبان دارت نیز به پایان رسید.
در جلسه بعد به آموزش isolate ها در زبان دارت Dart خواهیم پرداخت.
Mohammad Hosseini
سلام خیلی عالی توضیح دادین البته یکم کلا این مبحث پیچیده هستش و نیاز به تمرین داره تا قشنگ جا بیوفته اما در کل من متوجه شدم و بعد از تمرین مطمئنم بهتر توی ذهنم جا میگیره ، ممنون 🙂
مهدی
سلام وقت بخیر ممنون از مطالب خوبتون کاش در مورد stream های کتابخونه async هم مطلب بذارید
Arezo
سلام ممنون از شما خیلی عالی توضیع دادین اگر لطف کنید راجب permission هم کمی معلومات بدین ممنون میشم