[Dart] 비동기 프로그래밍

devvace ㅣ 2022. 12. 8. 23:55

# Future

- delayed

void main() {
	
	Future<String> name = Future.value('코드팩토리');

	addNumbers(1, 1);
}

void addNumbers(int: number1, int number2) {
	print('계산 시작: $number1 + $number2');

	// 2개의 파라미터
	// 1번 파라미터 - 지연할 시간
	// 2번 파라미터 - 지연 시간이 지난 후 실행할 함수
	Future.delayed(Duration(seconds: 2), (){
		print('계산 완료: $number1 + $number2 = ${number1 + number2}');
	});

	print('함수 완료')
}

 

- await

Future를 리턴해주는 함수만 await할 수 있다.

void addNumbers(int: number1, int number2) async { //async를 넣어야 await 사용가능
	print('계산 시작: $number1 + $number2');

	// 2개의 파라미터
	// 1번 파라미터 - 지연할 시간
	// 2번 파라미터 - 지연 시간이 지난 후 실행할 함수
	await Future.delayed(Duration(seconds: 2), (){
		print('계산 완료: $number1 + $number2 = ${number1 + number2}');
	});

	print('함수 완료')
}
void main() async {
	await addNumbers(1, 1);
	await addNumbers(2, 2);
}

// Future를 리턴해야지 await를 사용할 수 있기 때문에 앞에 `Future<void>` 사용
Future<void> addNumbers(int: number1, int number2) async {
	print('계산 시작: $number1 + $number2');

	await Future.delayed(Duration(seconds: 2), () {
		print('계산 완료: $number1 + $number2 = $(number1 + number2)');
	});

	print('함수 완료 : $number1 + $number2');
}

 

# Steam

import 'dart:async';

void main() {
  final controller = StreamController();
  // asBroadcastStream으로 해줘야 여러번 리스닝을 할 수 있는 스트림을 생성할 수 있음
  final stream = controller.stream.asBroadcastStream();
  
  final streamListener1 = stream.listen((val){
    print('Listener 1: $val');
  });
  
  final streamListener2 = stream.listen((val) {
    print('Listener 2: $val');
  });
  
  controller.sink.add(1);
  controller.sink.add(2);
  controller.sink.add(3);
  controller.sink.add(4);
  controller.sink.add(5);
}

- 중간에 'where'절을 넣어서 필터링 기능을 넣을 수도 있다.

import 'dart:async';

void main() {
  final controller = StreamController();
  // asBroadcastStream으로 해줘야 여러번 리스닝을 할 수 있는 스트림을 생성할 수 있음
  final stream = controller.stream.asBroadcastStream();
  
  final streamListener1 = stream.where((val) => val % 2 == 0).listen((val){
    print('Listener 1: $val');
  });
  
  final streamListener2 = stream.where((val) => val % 2 == 1).listen((val) {
    print('Listener 2: $val');
  });
  
  controller.sink.add(1);
  controller.sink.add(2);
  controller.sink.add(3);
  controller.sink.add(4);
  controller.sink.add(5);
}

// 결과
/*
Listener 2: 1
Listener 1: 2
Listener 2: 3
Listener 1: 4
Listener 2: 5
*/

 

- yield

import 'dart:async';

void main() {
  calculate(2).listen((val) {
    print('calculate(2): $val');
  });

  calculate(4).listen((val) {
    print('calculate(4): $val');
  });	
}

Stream<int> calculate(int number) async* {
	// yield를 사용해서 각 분기마다 리턴이 가능하게 된다.
  for(int i = 0; i < 5; i++) {
    yield i * number;
		await Future.delayed(Duration(seconds: 1));
  }
}

// 결과: await를 사용했지만, 두 함수가 번갈아 실행되면서 비동기 형태가 되는 것을 볼 수 있다.
/*
calculate(2): 0
calculate(4): 0
calculate(2): 2
calculate(4): 4
calculate(2): 4
calculate(4): 8
calculate(2): 6
calculate(4): 12
calculate(2): 8
calculate(4): 16
*/

 

- yield*

만약에 번갈아 실행되는 것이 아니라, 첫 번째 함수가 다 실행될때까지 기다리게 하고 싶다면, 'yield*' 키워드를 사용하면 된다.

import 'dart:async';

void main() {
  playAllStream().listen((val) {
    print(val);
  });
}

Stream<int> playAllStream() async* {
  // yield*을 하면 첫 번째 함수가 다 실행되어야지 다음 함수가 실행됨
  yield* calculate(1);
  yield* calculate(1000);
}

Stream<int> calculate(int number) async* {
  for(int i = 0; i < 5; i++) {
    yield i * number;
    
    await Future.delayed(Duration(seconds: 1));
  }
}

// 결과값
/*
0
1
2
3
4
0
1000
2000
3000
4000
*/