درباره برنامه نویسی ناهمزمان با استفاده از Future صحبت کردیم که چطوری از فیوچر استفاده کنیم تا بصورت ناهمزمان دو فعالیت رو در دارت انجام بدیم و گفتیم که در دارت ناهمزمانی با دو تایپ انجام میشه که یکی Future بود و یکی هم که قراره دربارش صحبت کنیم Stream هست پس اگر اون بخش رو نخوندی حتما پیشنهاد میکنم بری بخونی که اینجا به کارت میاد.
استریم ها درواقع یک جریان از دیتا هستن که بصورت ناهمزمان کار میکنن.
اگر بخوام زیر دیپلم و برای کسی بگم که تازه وارده بهتره بگم همون لیست خودمونه که حالا یکسری قابلیت هایی بهش دادن و بهش میگن ناهمزمان.
درواقع همون فانکشن هایی که روی لیست داشتیم رو اومده فقط تایپ خروجیش رو بصورت فیوچر کرده و یکم ریزه کاری داره که در ادامه تو کد میبینیم.
برای ساخت استریم راه های متعددی وجود داره یکی از روش ها با استفاده از فانکشن که استریم بر میگردونه
برای مثال
Stream<int> countStream(int to) async* {
for (int i = 1; i <= to; i++) {
yield i;
}
}
در دو نکته قابل توجه وجود داره
شرح کد بالا اینه که این فانکشن رو بهش هر عددی بدیم یه جریانی(لیست) از یک تا اون عدد رو به ما برمیگردونه، حالا من میام اینو فراخوانی میکنم
Future<void> main() async {
var stream = countStream(10);
final firstNumberInStream = await stream.first; // 1
}
در اینجا اومدم اون استریم خودم رو فراخوانی کردم و حالا جریانی از اعداد از یک تا 10 رو دارم میام و اولیش رو در میارم با که با استفاده از stream.first که فیوچر بهم میده ولی اومدم از await استفاده کردم که داده اصلی رو بهم بربگردونه همون عدد یک هست رو بربگردونه
متود های زیر رو میتونید ببینید که روی استریم قابل استفاده هست و من از اولیش توی مثال بالا استفاده کردم.
خودتون میتونید ببینید که تقریبا متود هاش با متود های لیست توی دارت برابری میکنه ولی چون خروجی بصورت Future هست پس یه ناهمزمانی توش رخ داده
Future<T> get first;
Future<bool> get isEmpty;
Future<T> get last;
Future<int> get length;
Future<T> get single;
Future<bool> any(bool Function(T element) test);
Future<bool> contains(Object? needle);
Future<E> drain<E>([E? futureValue]);
Future<T> elementAt(int index);
Future<bool> every(bool Function(T element) test);
Future<T> firstWhere(bool Function(T element) test, {T Function()? orElse});
Future<S> fold<S>(S initialValue, S Function(S previous, T element) combine);
Future forEach(void Function(T element) action);
Future<String> join([String separator = '']);
Future<T> lastWhere(bool Function(T element) test, {T Function()? orElse});
Future pipe(StreamConsumer<T> streamConsumer);
Future<T> reduce(T Function(T previous, T element) combine);
Future<T> singleWhere(bool Function(T element) test, {T Function()? orElse});
Future<List<T>> toList();
Future<Set<T>> toSet();
یکسری متود ها هستن که روی استریم اگر بزنیم استریم جدید با کمی تعدیل یا تغییر به ما بر میگردونه که تقریبا هم مثل لیست ها توی دارت هست که این متود ها عبارت از
Stream<R> cast<R>();
Stream<S> expand<S>(Iterable<S> Function(T element) convert);
Stream<S> map<S>(S Function(T event) convert);
Stream<T> skip(int count);
Stream<T> skipWhile(bool Function(T element) test);
Stream<T> take(int count);
Stream<T> takeWhile(bool Function(T element) test);
Stream<T> where(bool Function(T event) test);
ما گفتیم که استریم ها یک جریان هستن، حالا اینجاست که جریان بودن خودش رو به رخ میکشه.
فرض کنید که شما درحال پیام دادن به یک دوست خوب هستید، و دوست شما برای اینکه پیام هارو دریافت کنه باید تلفن همراهش روشن باشه که پیام ها یا لیستی از پیام های شما به اوشون برسه، پس دوست شما یک جریانی(استریم) رو داره. حالا اینجا شرکت مخابرات میاد و بین صحبت های شما و دوستتون میشینه و به پیام ها گوش میده به عبارتی listen میکنه و شما با هربار ارسال پیام (yield) میاد و پیام شمارو گوش میده.
خب بریم که پیاده سازیش کنیم.
حالا توی این مثال فرض کنید شما پیام رو هر سه ثانیه از یک تا هشت رو برای دوستتون می فرستید
Stream<int> sendMessage()async*{
for(int i = 1;i <= 8;i++){
await Future.delayed(Duration(seconds:3)); // سه ثانیه تاخیر
yield i;
}
}
void main(){
final stream = sendMessage();
stream.listen((value)=>print(value));
print("َAsync");
print("Stream");
}
توی اینجا استریم فرستنده پیام به نام sendMessage رو فراخوانی کردم که هر سه ثانیه بیاد عدد رو از یک تا هشت بفرسته توی جریان یا همون استریم که لیست خودمون میشه و بعد توی فانکشن اصلی (main) اومدم استریم رو فراخوانی کردم و سر راهش یک گوش دهنده (listen) قرار دادم و گفتم بهش هر وقت پیامی رو ارسال کرد یا همون yield کرد بیا گوش بده ببین چیه و برام پرینت کن
برای اینکه نا همزمانی رو نشون بدم اومدم دوتا پرینت هم بعدش گذاشتم که ببینید خروجی بصورت نا همزمان هست
و در نهایت خروجی بعد از 24 ثانیه:
َAsync
Stream
1
2
3
4
5
6
7
8
امیدوارم تونسته باشم استریم هارو بصورت ساده توضیح داده باشم و مطلب براتون مفید واقع شده باشه.
منبع من برای این مطلب وبسایت pub.dev هست با کمی تغییر.