[Dart] 다트 비동기 프로그래밍 - Future / async, await / Stream
비동기 프로그래밍?
: 함수 실행시 요청한 결과를 기다리거나, 대기하지 않고 바로 다음 코드를 진행!
응답 순서 != 요청한 순서
언제든 응답이 오면 그때 응답을 처리한다~
→ 컴퓨터 자원을 낭비하지 않고 더욱 효율적으로 코드를 실행할 수 있다.
* 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();
}