Flutter/Dart

[Dart] 다트 비동기 프로그래밍 - Future / async, await / Stream

jungha_k 2023. 6. 8. 14:07

비동기 프로그래밍? 

: 함수 실행시 요청한 결과를 기다리거나, 대기하지 않고 바로 다음 코드를 진행!

 

응답 순서 != 요청한 순서

언제든 응답이 오면 그때 응답을 처리한다~

→ 컴퓨터 자원을 낭비하지 않고 더욱 효율적으로 코드를 실행할 수 있다.


* Future

: 미래에 받아올 값

제네릭으로 어떤 미래의 값을 받아올지 정할 수 있다!

→ 서버 요청과 같이 오래 걸리는 작업을 기다린 다음 값을 받아오기 때문에 필요

Future<String> name;
Future<int> number; 
...

 

* Future.delayed() : 특정 기간 동안 아무것도 하지 않고 기다림

...(생략)

Future delayed(Duration(seconds: 3), (){
	print('$number1 + $number2 = ${number1 + number2}');
    });
    
    ...(생략)
}

delayed 되는 동안에도 모든 연산이 3초간 멈추는 것이 아니라

대기하지 않고 바로 다음 함수를 실행한다~

CPU의 리소스 낭비하지 않음! 따라서 요청~응답 시간이 다를 수 있다.

 


* async - await

: 단순히 Future, delayed 만 사용한다면 

코드가 작성된 순서대로 실행되지 않아 헷갈릴 수도 있다!

 

async, await : 코드 가독성 유지 가능

비동기 프로그래밍 특징을 그대로 유지하며, 코드 작성된 순서대로 프로그램 실행!

Future<void> addNumbers(int number1, int number2) async{⭐⭐
	print('$number1 + $number2 계산 시작!');
    ⭐⭐
   	await Future.delayed(Duration(seconds: 3), (){
    	print('$number1 + $number2 = ${number1 + number2}');
    });
    
    print('$number1 + $number2 코드 실행 끝');
}

* async : 함수 매개변수 정의 ~ 바디 사이에 입력

* await : 대기하고 싶은 비동기 함수 '앞에' 입력

 

 

* 결과값 반환받기 : async / await 키워드 사용한 함수에서도 결과값 받아내기! → Future 클래스 사용

void main() async{
  final result = await addNumbers(1,1);
  print('결괏값 $result');

  final result2 = await addNumbers(2,2);
  print('결괏값 $result2');
}

Future <int> addNumbers(int number1, int number2) async{
  print('$number1 + $number2 계산 시작!');
  
  await Future.delayed(Duration(seconds:3), (){
    print('$number1 + $number2 = ${number1 + number2}');
  });
  
  print('$number1 + $number2 코드 실행 끝');
  
  return number1 + number2;
}

// 출력 결과
1 + 1 계산 시작!
1 + 1 = 2
1 + 1 코드 실행 끝
결괏값 2
2 + 2 계산 시작! 
2 + 2 = 4
2 + 2 코드 실행 끝
결괏값 4

* Stream 

: 지속적으로 값을 반환시 사용

한번 listen 하면 Stream에 주입되는 모든 값들을 지속적으로 받아온다!

 

* Future

: 반환값을 딱 한 번 받아내는 비동기 프로그래밍에 사용

 

* Stream 사용법

: 플러터 기본 제공 패키지인 dart:async 패키지를 불러와야 한다!

다음 StreamController를 listen() 해야 값을 지속적으로 반환 받을 수 있다.

import 'dart:async';

void main(){
	final controller = StreamController();
    final stream = controller.stream;
	
    //Stream에 listen 함수 - 값이 주입될 때 마다 콜백 함수 실행
    final streamListener1 = stream.listen((val) {
    print(val);
    });
    
    // Stream 에 값을 주입하기
    controller.sink.add(1);
    controller.sink.add(2);
    controller.sink.add(3);
    controller.sink.add(4);
}

 

* Stream - 단 한번만 listen() 실행할 수 있다.

But 하나의 Stream 생성하고, listen() 함수를 실행하고 싶을 때가 있다!

 

* Broadcast Stream 

: Stream을 여러번 listen() 하도록 변환 가능

... 생략

final stream = controller.stream.asBroadcastStream();

... 생략

 

 

* StreamController 직접 사용하지 않고 직접 Stream 반환하는 함수 작성 가능!

 

함수가... 
Future 반환? async로 함수 선언, return 키워드로 값을 반환!

Stream 반환? async*로 함수 선언, yield 키워드로 값 반환!

import 'dart:async';

// Stream 반환 함수 : async* 로 선언
Stream <String> calculate(int number) async*{
  for (int i = 0 ; i < 5; i++){
  	// StreamController의 add 처럼 'yield'로 반환
    yield 'i = $i';
    await Future.delayed(Duration(seconds: 1));
  }
}

void playStream(){
	//listen 함수로 콜백 함수 입력
  calculate(1).listen((val){
    print(val);
  });
}

void main(){
  playStream();
}