Dart : https://dart.dev/guides/language/language-tour
- Dart 라이브러리는 Future 또는 Stream 객체를 반환하는 함수들이 많으며 이러한 함수는 비동기적이다
- 작업이 완료 될 때까지 기다리지 않고 시간이 많이 걸리는 작업 (ex: I/O) 을 설정 한 후 반환된다
- async 및 await 키워드는 비동기 프로그래밍을 지원하므로 동기 코드와 유사한 비동기 코드를 작성할 수 있다
- 참고 : https://dart.dev/codelabs/async-await
1. Declaring async functions
- async 함수는 본문이 async 한정자로 표시된 함수로 함수에 async 키워드를 추가하면 Future가 반환된다
String lookUpVersion() => '1.0.0';
// async 함수로 변경
Future<String> lookUpVersion() async => '1.0.0';
2. Future
- Dart 라이브러리 전체에 나타나며, 종종 비동기 메서드에 의해 반환되는 객체이다
- future 는 Future 클래스의 인스턴스이다
- future 는 비동기 작업의 결과를 나타내며 미완료 또는 완료의 두 가지 상태를 가질 수 있다
2-1. Uncompleted
- 값을 생성하기 전 future 의 상태를 나타내는 Dart 용어이다
- 비동기 함수를 호출하면 완료되지 않은 future 가 반환된다
- 해당 future 는 함수의 비동기 작업이 완료되거나 오류가 발생하기를 기다리고 있는다
2-2. Completed
- 비동기 작업이 성공하면 future 는 값으로 완료되고 그렇지 않으면 오류와 함께 완료된다
Completing with a value
- Future<T> 타입의 future 는 T 타입의 값으로 완료된다
- 예를 들어 Future<String> 은 문자열 값을 생성한다
- Future 가 사용 가능한 값을 생성하지 않으면 Future 타입은 Future<void> 이다
Completing with an error
- 어떤 이유로든 함수가 수행한 비동기 작업이 실패하면 future 는 오류와 함께 완료된다
3. Handling Futures
- 완료된 Future 의 결과가 필요한 경우 두 가지 옵션이 있다
- async 와 await 키워드 사용
- Future API 사용
- async 와 await 키워드를 사용하는 코드는 비동기적이지만 동기 코드와 비슷하다
- 아래 코드는 비동기 함수의 결과를 기다리는데 await 을 사용하는 일부 코드이다
await lookUpVersion();
// await 은 async 키워드가 지정된 async 함수 내에서 사용해야 한다
Future checkVersion() async {
var version = await lookUpVersion();
// Do something with version
}
// async 함수에서 await 을 여러번 사용할 수 있다
var entrypoint = await findEntrypoint();
var exitCode = await runExecutable(entrypoint, args);
await flushThenExit(exitCode);
- async 함수는 시간이 많이 걸리는 작업을 수행 할 수 있지만 작업을 기다리지는 않는다
- 대신 async 함수는 첫 번째 await 표현식을 만날 때까지만 실행된다
- 그런 다음 Future 객체를 반환하고 await 표현식은 해당 객체를 사용할 수 있을 때까지 실행을 일시 중지하고 완료된 후 실행을 재개한다
// await 을 사용하는 코드에서 try-catch-finally 로 에러를 다룰 수 있다
try {
version = await lookUpVersion();
} catch (e) {
// React to inability to look up the version
}
- await 표현식에서 expression 의 값은 일반적으로 Future 이다
- 그렇지 않은 경우 값은 자동으로 Future 로 래핑된다
- await 사용 시 컴파일 타임 오류가 발생하면 await 이 비동기 함수에 있는지 확인해야 한다
- 예를 들어 앱의 main() 함수에서 await 을 사용하려면 main()의 본문을 async 로 표시해야한다
Future main() async {
checkVersion();
print('In main: version is ${await lookUpVersion()}');
}
4. Handling Streams
- 스트림에서 값을 가져와야하는 경우 두 가지 옵션이 있다
- async 또는 비동기 for loop (await for) 를 사용한다
- Stream API를 사용한다
- await for 를 사용하기 전에 코드가 더 명확하고 스트림의 모든 결과를 기다리고 싶은지 확인해야한다
- 예를 들어, UI 프레임 워크는 끝없는 이벤트 스트림을 전송하기 때문에
일반적으로 UI 이벤트 리스너에 대해 await를 사용하지 않아야한다 - 아래 await for 예제에서 expression 의 값은 Stream 유형이어야한다
- 아래 순서대로 실행한다
- 스트림이 값을 방출 할 때까지 기다린다
- 방출된 값으로 설정된 변수를 사용하여 for loop 의 내부를 실행한다
- 스트림이 닫힐 때까지 1, 2 를 반복한다
- 스트림 수신을 중지하려면 break 또는 return 문을 사용할 수 있다
await for (varOrType identifier in expression) {
// Executes each time the stream emits a value.
}
- 비동기 for loop 를 구현할 때 컴파일 타임 에러가 발생하면 aync 함수 내부에 await for 가 있는지 확인해야 한다
Future main() async {
// ...
await for (var request in requestServer) {
handleRequest(request);
}
// ...
}
5. Generators
- 일련의 값을 지연 생성해야하는 경우, generator 함수를 사용할 수 있다
1-1. Synchronous generator
- Iterable 객체를 반환한다
- synchronous generator 함수를 구현하려면, 함수 본문에 sync* 로 표시하고 yield 문을 사용하여 값을 제공한다
Iterable<int> naturalsTo(int n) sync* {
int k = 0;
while (k < n) yield k++;
}
- generator 가 재귀면 yield* 를 사용하여 성능을 향상시킬 수 있다
Iterable<int> naturalsDownFrom(int n) sync* {
if (n > 0) {
yield n;
yield* naturalsDownFrom(n - 1);
}
}
1-2. Asynchronous generator
- Stream 객체를 반환한다
- asynchronous generator 함수를 구현하려면, 함수 본문에 sync* 로 표시하고 yield 문을 사용하여 값을 제공한다
Stream<int> asynchronousNaturalsTo(int n) async* {
int k = 0;
while (k < n) yield k++;
}
'기타개발 > Flutter' 카테고리의 다른 글
Flutter : StatefulWidget & StatelessWidget (0) | 2020.09.13 |
---|---|
Dart # 11 : Callable classes, Isolates, Typedefs (0) | 2020.08.28 |
Dart #9 : Library (1) | 2020.08.28 |
Dart #8 : Generics (0) | 2020.08.28 |
Dart #7 : Extension method, Enum, Mixin (0) | 2020.08.28 |
댓글