Dart는 동기, 비동기 프로그래밍을 지원한다.
- 동기 : 요청하고 나서 응답이 올 때 까지 대기했다가 응답을 받으면 다음 코드 진행
- 비동기 : 요청하고 응답을 받지 않아도 다음 코드 진행
예를 들어 DB에서 게시판의 글을 가져오는 작업의 경우 등 시간이 걸리는 작업은 동기로 실행하면 앱이 매우 느려지기 때문에 이런 경우 비동기로 처리해야 한다.
🎆 다트 비동기 프로그래밍
1. Future
- Future 클래스는 미래에 받아올 값을 말하며, List나 Set처럼 제네릭으로 받아올 값을 정할 수 있다.
void main(){
Future<String> name; // 받아올 String값
Future<int> number; // 받아올 int값
Future<bool> isOpened; // 받아올 boolean값
}
- Future.delayed는 특정 기간동안 아무 것도 하지 않고 대기하였다가, 일정 시간 후 콜백 함수를 실행한다.
- 아래 출력 순서를 보면 '1 + 1 코드 실행 끝' 문구가 먼저 출력된 후 future.delayed 대기가 끝나고 계산결과가 마지막으로 출력되는 모습을 확인할 수 있다.
void main() {
addNumbers(1, 1);
}
void addNumbers(int number1, int number2){
print('$number1 + $number2 계산 시작!');
Future.delayed(Duration(seconds: 3), (){ // Future.delayed()를 사용하면 일정 시간 후에 콜백 함수를 실행할 수 있음
print('$number1 + $number2 = ${number1 + number2}');
});
print('$number1 + $number2 코드 실행 끝');
}
// 실행결과
// 1 + 1 계산 시작!
// 1 + 1 코드 실행 끝
// 1 + 1 = 2
2. async와 await
- Future에서는 코드가 작성된 대로 실행되지 않아 혼동될 수 있는 문제가 있다. async와 await는 이를 방지하고 코드 가독성을 유지시킬 수 있는 장점이 있다.
- 아래 코드를 보면 addNumbers(1, 1)이 끝나기 전에 대기 없이 addNumbers(2,2)가 실행되었다. 이는 addNumbers() 함수가 비동기 프로그래밍으로 실행되었기 때문이다.
void main() {
addNumbers(1, 1);
addNumbers(2, 2);
}
void addNumbers(int number1, int number2) async { // async 키워드는 함수 매개변수 정의와 바디 사이에 입력
print('$number1 + $number2 계산 시작!');
await Future.delayed(Duration(seconds: 3), (){ // await는 대기하고 싶은 비동기 함수 앞에 입력
print('$number1 + $number2 = ${number1 + number2}');
});
print('$number1 + $number2 코드 실행 끝');
}
// 실행결과
// 1 + 1 계산 시작!
// 2 + 2 계산 시작!
// 1 + 1 = 2
// 1 + 1 코드 실행 끝
// 2 + 2 = 4
// 2 + 2 코드 실행 끝
- 만약 addNumbers() 코드자체도 순서대로 실행되도록 하려면 아래와 같이 코드를 수정한다.
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: 3), (){
print('$number1 + $number2 = ${number1 + number2}');
});
print('$number1 + $number2 코드 실행 끝');
}
// 실행결과
// 1 + 1 계산 시작!
// 1 + 1 = 2
// 1 + 1 코드 실행 끝
// 2 + 2 계산 시작!
// 2 + 2 = 4
// 2 + 2 코드 실행 끝
- 일반 함수와 같이 결과값을 반환받으려면 아래와 같이 변수에 할당하여 사용할 수 있다.
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
3. Stream
- 반환값을 지속적으로 받아오고 싶을 경우 Stream을 사용한다.(Future는 반환값을 딱 한번 반환)
- Stream을 사용하려면 dart:async 패키지를 로드해야 한다. → import 'dart:async'
- controller = StreamController(); 와 같이 stream controller를 선언하여 이를 통해 stream을 로드하여 사용한다.
- Stream.listen() : 값이 주입될 때마다 콜백 함수 실행
- sink.add() : stream에 값을 주입
import 'dart:async'; // 패키지 로드
void main() {
final controller = StreamController(); // StreamController 선언
final stream = controller.stream; // Stream 로드
final streamListener1 = stream.listen((val) { // Stream에 listen() 함수 실행 : 값이 주입될 때마다 콜백 함수를 실행 가능
print(val);
});
// sink.add() : Stream에 값을 입력
controller.sink.add(1);
controller.sink.add(2);
controller.sink.add(3);
controller.sink.add(4);
}
// 실행결과
// 1
// 2
// 3
// 4
- 브로드캐스트 스트림 : 하나의 스트림을 생성하고 여러 번 listen()함수를 실행하고 싶을 때
- controller.stream.asBroadcastStream(); 으로 BroadcastStream 객체 생성
import 'dart:async';
void main() {
final controller = StreamController();
final stream = controller.stream.asBroadcastStream(); // 여러 번 리슨할 수 있는 Broadcaste Stream 객체 생성
final streamListener1 = stream.listen((val) { // 첫 번째 listen() 함수
print('listening 1');
print(val);
});
final streamListener2 = stream.listen((val) { // 두 번째 listen() 함수
print('listening 2');
print(val);
});
controller.sink.add(1); // add()를 실행할 때마다 listen()하는 모든 콜백 함수에 값이 주입
controller.sink.add(2);
controller.sink.add(3);
}
// 실행결과
// listening 1
// 1
// listening 2
// 1
// listening 1
// 2
// listening 2
// 2
// listening 1
// 3
// listening 2
// 3
- 함수로 Stream 반환 : 이는 async*로 함수를 선언하고 yield 키워드로 값을 반환(Stream controller를 사용하지 않음)
import 'dart:async';
Stream<String> calculate(int number) async* { // Stream을 반환하는 함수를 async*로 선언
for (int i = 0; i < 5; i++) {
yield 'i = $i'; // yield 키워드를 이용해서 값 반환
await Future.delayed(Duration(seconds: 1));
}
}
void playStream() {
calculate(1).listen((val) { // listen() 함수로 콜백 함수 입력
print(val);
});
}
void main() {
playStream();
}
// 실행결과
// i = 0
// i = 1
// i = 2
// i = 3
// i = 4
'DEV > dart & flutter' 카테고리의 다른 글
Dart 객체지향 프로그래밍, 클래스 (1) | 2023.12.31 |
---|---|
Dart 기본 문법 정리 (0) | 2023.12.27 |
댓글