비동기 프로그래밍

shin·2022년 10월 1일
0

Dart

목록 보기
18/20

Future

void main() {
  // Future - 미래
  // 미래에 받아올 값
  
  Future<String> name = Future.value('코드팩토리');
  Future<int> number = Future.value(1);
  Future<bool> isTure = Future.value(true);
}

delayed

  • 2개의 파라미터를 갖는다
  • 1번 파라미터는 얼마나 지연할 것인지 지연할 기간을 설정한다. Duration
  • 2번 파라미터는 지연 시간이 지난후 실행할 함수를 작성한다.
void main() {
  
  print('함수 시작');
  
  Future.delayed(Duration(seconds:2), (){
    print('Delay 끝');
  });
}

함수시작
.
. 2초 후
.
Delay 끝

활용

  • 서버 시뮬레이션
  • Future를 사용해서 async 프로그래밍을 할 수 있다.
void main() {
  
  addNumbers(1,1);
}

void addNumbers(int number1, int number2){
  print('계산시작 : $number1 + $number2'); 
  
  // 서버 시뮬레이션
  Future.delayed(Duration(seconds: 2),(){
    print('계산 완료: $number1 + $number2 = ${number1 + number2}');
  });
  
  print('함수 완료');
}

계산시작 : 1 + 1
함수 완료
.
. 2초 후
.
계산 완료: 1 + 1 = 2
  • 계산시작 : 1 + 1 출력 후 2초를 기다리고 함수 완료가 실행되는 것이 아니라 2초가 지나가기 전에 계산 완료: 1 + 1 = 2 가 실행되고 함수 완료가 실행된다.

async & await

  • await 키워드를 사용하기 전에 파라미터와 {} 사이에 async를 넣어야 한다.
  • Future와 관련된 함수 (async 함수) 앞에 await를 작성한다.
void main() {

  addNumbers(1,1);

}

void addNumbers(int number1, int number2) async {
  print('계산시작 : $number1 + $number2'); 
  
  // 서버 시뮬레이션
  await Future.delayed(Duration(seconds: 2),(){
    print('계산 완료: $number1 + $number2 = ${number1 + number2}');
  });
  
  print('함수 완료 : $number1 + $number2');
}

계산시작 : 1 + 1
.
. 2초 후
.
계산 완료: 1 + 1 = 2
함수 완료 : 1 + 1
  • 계산시작 : 1 + 1 실행된 후 2초 후에 계산 완료: 1 + 1 = 2 함수 완료 : 1 + 1가 실행됐다.
  • 이 코드만 살펴보면 cpu가 2초 동안 아무것도 안하고 기다리고 있는 것처럼 보인다. 실제로는 그렇지 않다는 것을 증명해 보이면 아래와 같다.
void main() {
  addNumbers(1,1);
  addNumbers(2,2);
}

void addNumbers(int number1, int number2) async {
  print('계산시작 : $number1 + $number2'); 
  
  // 서버 시뮬레이션
  await Future.delayed(Duration(seconds: 2),(){
    print('계산 완료: $number1 + $number2 = ${number1 + number2}');
  });
  
  print('함수 완료 : $number1 + $number2');
}

계산시작 : 1 + 1
계산시작 : 2 + 2
.
. 2초 후
.
계산 완료: 1 + 1 = 2
함수 완료 : 1 + 1
계산 완료: 2 + 2 = 4
함수 완료 : 2 + 2
  1. 먼저 addNumbers(1,1)이 실행되면서 계산시작 : 1 + 1이 출력된다.
  2. await에 걸리면서 2초 동안 실행을 보류하면서 다음 실행할 작업을 찾는다.
  3. addNumbers(2,2)가 실행이 되면서 계산시작 : 2 + 2이 실행된다.
  4. 2초가 지나면 나머지 addNumbers(1,1)이 실행되고 addNumbers(2,2)이 실행된다 .
  • addNumbers(1,1)addNumbers(2,2)를 논리적으로 실행을 할 수 있는 코드를 작성할 수 있다.
void main() async{
  await addNumbers(1,1);
  await addNumbers(2,2);
}

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');
}

  • main() 함수에 async를 작성한다.
  • addNumbers()await를 작성하면 에러가 발생하게 되는데 addNumbers()Future를 리턴 해주지 않기 때문이다.
  • addNumbers()Future를 작성하고 <void>를 작성해 주면 된다.

Stream

  • Future를 실행하게 되면 await를 통해서 값을 기다리고 한 개의 값을 반환하게 된다.
    Future의 특징은 하나의 함수에서 한 개의 값은 반환한다는 것이다. 일반적으로 모든함수가 동일하다

  • 여러번 값을 받아낼려면 여러번의 함수를 실행해야 한다.

  • 이러한 점을 보완해서 나온 것이 Stream 이다

  • Stream을 직역해보면 계곡인것처럼 데이터가 계속 흐른다. 이때 yield라는 키워드를 통해서 계속 값을 반환할 수 있는데 Stream을 직접 닫을 때까지 사용할 수 있다.

  • Stream을 사용하기전에 패키지를 불러와야한다.

import 'dart:async';
import 'dart:async';

void main() {
  final controller = StreamController();
  // StreamController();는 dart:async에서 불러올 수 있는 클래스이다.
  final stream = controller.stream;
  // StreamController()를 통해서 stream을 가져올 수 있다.
  
  final streamListener1 = stream.listen((val){
    print('Listener 1 : $val');
  });
  // stream에서 listen() 함수를 사용할 수 있다.
  // listen()은 함수를 받게 되는데 들어가는 함수의 파라미터에 값을 받는다.
  // 첫번째 파라미터의 값을 듣고 있다가 값이 들어오면 이 함수를 실행하게 되는것이다.
  
  controller.sink.add(1);
  // controller에 값을 넣어준다.
  
}
Listener 1 : 1

Broadcast Stream

  • 리소스가 허용하는 한에서 streamListener를 여러번 생성할 수 있다.
import 'dart:async';

void main() {
  final controller = StreamController();
  final stream = controller.stream;
  // controller.stream에서는 기본적으로 한번만 리스닝을 할 수 있는 리소스가 생긴다.
  // asBroadcastStream();를 뒤에 붙이면 여러번 리스닝을 사용할 수 있다.
  
  final streamListener1 = stream.listen((val){
    print('Listener 1 : $val');
  });
  
   final streamListener2 = stream.listen((val){
    print('Listener 2 : $val');
  })
  // 리스너2를 선언했다.
  
  controller.sink.add(1);
  controller.sink.add(2);
  controller.sink.add(3);
  controller.sink.add(4);
  controller.sink.add(5);
}
Listener 1 : 1
Listener 2 : 1
Listener 1 : 2
Listener 2 : 2
Listener 1 : 3
Listener 2 : 3
Listener 1 : 4
Listener 2 : 4
Listener 1 : 5
Listener 2 : 5

Stream 값 변형하기

  • streamListener1 에서는 짝수 streamListener2에서는 홀수를 출력해보겠다.
import 'dart:async';

void main() {
  final controller = StreamController();
  final stream = controller.stream.asBroadcastStream();

  final streamListener1 = stream.where((val) => val % 2 == 0).listen((val) {
    print('Listener 1 : $val');
  });
  
  // 함수형 프로그래밍에서 사용했던 함수를 사용할 수 있다.
  // where를 사용해서 짝수와 홀수를 구분해서 출력한다.

  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

0개의 댓글