일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 웹크롤러
- Class
- function
- 파이썬
- 다트
- 함수
- 코틀린
- Android
- python
- ML
- textstyle
- kotlin
- 크롤러
- crawler
- text
- Flutter
- pushnamed
- set
- package
- 클래스
- Yocto
- DART
- map
- 콜렉션
- animation
- variable
- import
- List
- Collection
- 플러터
- Today
- Total
조용한 담장
Dart : Asynchronous programming 본문
Dart : Asynchronous programming
Dart 의 비동기 프로그래밍.
Asynchrony support
비동기 프로그래밍은 Future or Stream 을 통해 지원한다.
아래 코드를 보면서 감을 잡아보자.
-
main()
에서 첫번째print()
를 출력하고 두번째print()
에서 출력할 내용을await createOrderMessage()
이 리턴할 때 까지 기다린다. -
createOrderMessage()
에서var order
변수를 생성하고 값을 설정하기 위해await getUserOrder()
의 리턴값을 기다린다. -
getUserOrder()
에서Future.delayed()
가 4초 후 'Large Latte' 문자열을 리턴한다. -
await getUserOrder()
가 문자열을 리턴하면createOrderMessage()
의 나머지 코드가 수행되어 'Your order is: $order' 문자열을 리턴한다. -
createOrderMessage()
이 리턴되어 기다리던print()
동작이 수행되어 인자로 전달된 'Your order is: Large Latte' 문자열을 출력한다.
// Asynchronous
Future<String> createOrderMessage() async {
var order = await getUserOrder();
return 'Your order is: $order';
}
Future<String> getUserOrder() {
// Imagine that this function is
// more complex and slow.
return
Future.delayed(
Duration(seconds: 4), () => 'Large Latte');
}
// Asynchronous
main() async {
print('Fetching user order...');
print(await createOrderMessage());
}
// 'Fetching user order...'
// 'Your order is: Large Latte'
Future class
An object representing a delayed computation.
A Future is used to represent a potential value, or error, that will be available at some time in the future.
Future 는 특정 코드가 비동기적으로 수행된 후 의 결과가 저장되면 콜백으로 알려주고 저장된 데이터를 읽을 수 있게 된다.
future 의 state 는 Uncompleted 와 Completed 로 나눠진다.
- Uncompleted : 비동기로 수행되고 있는 함수, 코드가 완료되지 않아 결과나 error 를 기다리고 있는 상태이다.
- Completed
- Completing with a value : 비동기 함수, 코드 수행이 완료되어 정상적인 결과 값으로 Future 나 Future 를 가지고 있다.
- Completing with an error : 비동기 함수, 코드 수행에 에러가 발생하여 에러값을 가지고 있다.
If a future doesn’t produce a usable value, then the future’s type is
Future
.
Future<void>
는 리턴값이 없는 void 함수를 수행할때 가지게 되는 Future 타입이다.
아래처럼 Future 의 데이터를 읽어야 하는 receiver 는 콜백 함수를 등록해서 결과값을 처리 한다.
Future<int> future = getFuture();
future.then((value) => handleValue(value))
.catchError((error) => handleError(error));
위의 콜백함수와 그 결과 처리 코드를 좀 더 간결하게 쓸 수 있도록 async, await 를 제공한다.
async, await
async
로 표시된 함수는 내부 코드에서 await
키워드를 만나면 그 뒤의 동작을 비동기적으로 처리하고 결과를 기다리며 진행을 멈추고 Future
가 리턴되면 다시 동작을 수행한다.
async function
An
async
function is a function whose body is marked with theasync
modifier. Adding theasync
keyword to a function makes it return a Future.
함수명 뒤에 async
키워드를 가진 함수로 비동기적인 속성을 가지게 되고 그 결과로 Future 를 리턴한다.
Future<String> lookUpVersion() async => '1.0.0';
await
는 async
function 내에서만 사용해야 한다.
Future checkVersion() async {
var version = await lookUpVersion();
// Do something with version
}
Future main() async {
checkVersion();
print('In main: version is ${await lookUpVersion()}');
}
위 코드 동작을 보면, Future 를 리턴하는 async
function 인 checkVersion()
은 await
를 만나면 자신의 동작은 멈추고 비동기 적으로 lookUpVersion()
이 수행되며 그 결과(Future)가 리턴되면 var version
에 값을 저장하고 나머지 코드를 수행한다.
await
는 error 도 전달하는 데 try
, catch
, and finally
를 통해 처리한다.
try {
version = await lookUpVersion();
} catch (e) {
// React to inability to look up the version
}
async
function 안에서 await
는 여러번 사용될 수 있다.
// wait three times.
var entrypoint = await findEntrypoint();
var exitCode = await runExecutable(entrypoint, args);
await flushThenExit(exitCode);
Future class 의 메소드들을 then()
을 사용하여 구현하는 코드 보다 await
/async
를 사용한 코드가 조금 더 간단하고 이해하기 좋은 장점이 있다.
PREFER async/await over using raw futures.
// async/await
Future<int> countActivePlayers(String teamName) async {
try {
var team = await downloadTeam(teamName);
if (team == null) return 0;
var players = await team.roster;
return players.where((player) => player.isActive).length;
} catch (e) {
log.error(e);
return 0;
}
}
// Future methods
Future<int> countActivePlayers(String teamName) {
return downloadTeam(teamName).then((team) {
if (team == null) return Future.value(0);
return team.roster.then((players) {
return players.where((player) => player.isActive).length;
});
}).catchError((e) {
log.error(e);
return 0;
});
}
async 를 쓰지 않아도 되는 경우엔 생략하자.
Future afterTwoThings(Future first, Future second) {
return Future.wait([first, second]);
}
// bad
Future afterTwoThings(Future first, Future second) async {
return Future.wait([first, second]);
}
위 예제의 afterTwoThings()
는 async
없이도 동작이 동일하다.
사용해야 하는 예제로 아래의 세가지 경우를 참고한다.
// 1. await 를 사용하는 경우
Future usesAwait(Future later) async {
print(await later);
}
// 2. 비동기적으로 error 를 리턴하는 경우.
// Future.error() 메소드 보다 코드가 간단해 진다.
Future asyncError() async {
throw 'Error!';
}
// 3. Future 를 통해 값을 전달하는 경우.
// Future.value() 메소드 보다 코드가 간단해 진다.
Future asyncValue() async => 'value';
Future Examples
Future class 의 동작을 확인해본 간단한 snippet.
지정한 결과값을 가진 future 를 생성하는 constructor
특정 시간 후에 동작을 수행하는 future 를 생성하는 constructor
timeout()
메소드를 이용해 일부러 에러를 발생하는 예제 포함.
Future.forEach(Iterable elements, FutureOr action(T element))
elements 각각의 값을 가지고 순서대로 action 을 수행하여 최종 결과를 future 로 만드는 static method.
모든 action 이 정상 수행 되면 null
을 가지는 future 를 리턴하는 특성 때문에 결과값을 전달하는 용도로 사용할 수는 없다.
Future.wait()
는 값을 전달할 수 있다.
아래 코드에서 elements 의 순서대로 수행되나 결과의 순서는 각각의 비동기 수행의 결과에 따라 다를 것이다.
Future.wait(IterableFuture futures, { bool eagerError: false, void cleanUp(T successValue) })
Future.error('Future.error()'),
를 주석처리 하면 두번째 output 결과를 얻는다.
Future.doWhile(FutureOr action())
false
를 리턴할때 까지 action 을 반복 수행한다.
Reference
Asynchronous programming: futures,async,await
'Dart' 카테고리의 다른 글
Dart : Collections (0) | 2019.11.19 |
---|---|
Dart : print (0) | 2019.11.04 |
Dart : Class (0) | 2019.10.02 |
Dart : Exceptions (0) | 2019.09.20 |
Dart : Control flow statements (0) | 2019.09.17 |