시리즈

[번역] Dart 비동기 프로그래밍 : futures, async, await

20190923
async
await
dart
flutter
future

원문 Asynchronous programming: futures, async, await

  1. 언제, 어떻게 async와 await를 사용하는가?
  2. async와 await로 실행 순서에 영향을 주는 방법.
  3. async 함수에 try-catch 문을 사용해서 비동기 에러를 처리하는 법.

비동기 코드의 중요성

비동기 작업은 다른 작업들이 비동기 작업이 완료 되는 것을 기다리는 동안에 하던 것을 완성하도록 합니다.
비동기 작업의 예
비동기 작업을 위해 Future 클래스와 async, await 키워드를 사용합니다. 

용어 정리
 
 동기 작업(synchorous operation)  동기 작업은 다른 작업이 실행되는 것을 막습니다.
 동기 함수(synchorous function) 동기 함수는 동기 작업만을 수행합니다.
 비동기 작업(asynchorous operation) 초기화되고 나면, 다른 작업을 비동기 작업이 끝나기 전에도 실행할 수 있습니다.
 비동기 함수(asynchorous function) 비동기 함수는 최소 하나의 비동기 작업을 수행하고, 동기 작업도 수행할 수 있습니다.


Future

future는 Future 클래스의 인스턴스 입니다. future는 비동기 작업의 결과를 2개의 상태로 표현 합니다. 상태에는 완성(completed)된 상태와, 미완성(uncompleted) 상태로 나뉩니다.

미완성(uncompleted) 상태는 값을 만들어 내기 전의 future의 상태를 말합니다.
 

미완성 Uncompleted

비동기 함수를 호출하면, 미완성 future 를 리턴합니다. future는 함수의 비동기 작업이 끝나거나 에러를 던지는 것을 기다립니다. 

완성 Completed

비동기 작업이 성공하면, future는 값을 완성하게 됩니다. 작업이 실패하면 에러로 완성됩니다. 

값으로 완성
Future 타입의 future는 T 타입 값으로 완성됩니다. 사용가능한 값을 만들지 않는 경우에는 Future 값을 사용합니다.
에러로 완성
비동기 작업이 어떤 이유로 실패하면 에러로 future가 완성됩니다.

예시 : 값으로 완성

1
2
3
4
5
6
7
8
9
future Future<void> getUserOrder() {
 // Imagine that this function is fetching user info from another service or database
 return Future.delayed(Duration(seconds: 3), () => print('Large Latte'));
}

main() {
 getUserOrder();
 print('Fetching user order...');
}

Fetching user order...
Large Latte 

getUserOrder() 가 실행되면 값이 리턴되는 것이 아니라 3초를 기다렸다가 print('Large Latte') 를 하는 future가 리턴됩니다.


예시 : 에러로 완성

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
Future<void> getUserOrder() {
// Imagine that this function is fetching user info but encounters a bug
 return Future.delayed(Duration(seconds: 3),
 () => throw Exception('Logout failed: user ID is invalid'));
}

main() {
 getUserOrder();
 print('Fetching user order...');
}

Fetching user order...
Uncaught Error: Exception: Logout failed: user ID is invalid 


3초 뒤에 에러 메시지가 나옵니다.


async and await

async, await 은 함수를 정의하고 그 결과를 사용하기 위한 선언적인(declarative) 방법을 제공합니다.
  • async 함수를 정의하려면 함수 몸체 전에 async 를 추가합니다.
  • await 키워드는 async 함수에서만 사용할 수 있습니다.
비동기 main 함수 

1
main() async {}

Dart에서는 타입 추론을 하지만 제품 단계 코드에서는 타입을 지정하는 것을 추천합니다. 

1
Future<void> main() async {}

async 함수에서는 await 키워드를 사용해서 future가 완성되는 것을 기다릴 수 있습니다.

 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
32
33
34
35
36
37
38
39
40
41
42
43
44
// Synchronous
String createOrderMessage() {
 var order = 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'); 
}

// Synchronous
main() {
 print('Fetching user order...');
 print(createOrderMessage());
}

// 'Fetching user order...'
// 'Your order is: Instance of _Future'
 // 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'

  • createOrderMessage 함수의 리턴 타입을 String에서 Future 으로 바꿈
  • async 키워드를 통해서 createOrderMessage, main 함수가 비동기 함수가 됨.
  • 비동기문의 완성된 결과를 받기 위해서 await 키워드를 getUserOrder와 createOrderMessage에 사용함. 즉, Future를 리턴하는 함수들을 호출할 때 await를 붙임.

async 와 await

첫 await 키워드가 나올 때까지는 async 함수는 동기 실행을 합니다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import 'dart:async';

void createOrderMessage () async {
  print('Awaiting user order...');
  var order = await getUserOrder();
  print('Your order is: $order');
}

Future<String> getUserOrder() {
  // Imagine that this function is more complex and slow.
  return Future.delayed(Duration(seconds: 4), () => 'Large Latte');
}

main() async {
  countSeconds(4);
  await createOrderMessage();
}

// You can ignore this function - it's here to visualize delay time in this example.
void countSeconds(s) {
  for( var i = 1 ; i <= s; i++ ) { 
      Future.delayed(Duration(seconds: i), () => print(i));
   }
}


에러 다루기

try-catch 를 사용합니다. 

1
2
3
4
5
6
  try {
    var order = await getUserOrder();
    print('Awaiting user order...');
  } catch (err) {
    print('Caught error: $err');
  }

.

piano (press key Q)

Categories

flutter ( 82 ) dart ( 34 ) android ( 32 ) kotlin ( 11 ) plugin ( 8 ) provider ( 8 ) vim ( 7 ) bloc ( 6 ) iOS ( 6 ) state management ( 6 ) 플러터 ( 6 ) PS ( 5 ) algorithm ( 5 ) architecture ( 5 ) async ( 5 ) getx ( 5 ) java ( 5 ) API ( 4 ) BOJ ( 4 ) class ( 4 ) daily ( 4 ) git ( 4 ) golang ( 4 ) memo ( 4 ) riverpod ( 4 ) state ( 4 ) stream ( 4 ) test ( 4 ) web ( 4 ) widget ( 4 ) windows ( 4 ) HTTP ( 3 ) androidX ( 3 ) app state ( 3 ) context ( 3 ) crash ( 3 ) db ( 3 ) editor ( 3 ) error ( 3 ) extension ( 3 ) github ( 3 ) hive ( 3 ) ide ( 3 ) package ( 3 ) pubspec ( 3 ) python ( 3 ) syntax ( 3 ) vscode ( 3 ) app icon ( 2 ) await ( 2 ) chocolatey ( 2 ) consumer ( 2 ) cp949 ( 2 ) deployment ( 2 ) dev ( 2 ) flavor ( 2 ) gesture ( 2 ) globalkey ( 2 ) go ( 2 ) google ( 2 ) hack ( 2 ) js ( 2 ) json ( 2 ) key ( 2 ) keystore ( 2 ) list ( 2 ) listview ( 2 ) lock ( 2 ) mac ( 2 ) map ( 2 ) navigation ( 2 ) nosql ( 2 ) project ( 2 ) pub ( 2 ) recyclerview ( 2 ) rxdart ( 2 ) sdk ( 2 ) selector ( 2 ) setting ( 2 ) size ( 2 ) soc ( 2 ) synchronized ( 2 ) tdd ( 2 ) tip ( 2 ) version ( 2 ) viewmodel ( 2 ) vundle ( 2 ) webview ( 2 ) xcode ( 2 ) yaml ( 2 ) ( 2 ) 플러터 단점 ( 2 ) 16.0 ( 1 ) 2.0 ( 1 ) 2023 ( 1 ) AATP2 ( 1 ) ChangeNotifierProvider ( 1 ) Example ( 1 ) Guava ( 1 ) ImageReader ( 1 ) Mo's algorithm ( 1 ) OAuth2 ( 1 ) OpenGL ( 1 ) Oreo ( 1 ) ProgressBar ( 1 ) REST API ( 1 ) Trie ( 1 ) activity ( 1 ) adaptive ( 1 ) android P ( 1 ) android context ( 1 ) android11 ( 1 ) apktool2 ( 1 ) app exit ( 1 ) append ( 1 ) appicon ( 1 ) arkit ( 1 ) array ( 1 ) asciidoc ( 1 ) async * ( 1 ) async* ( 1 ) audio ( 1 ) authorization ( 1 ) await for ( 1 ) behaviorsubject ( 1 ) beta ( 1 ) binary ( 1 ) binarysearch ( 1 ) blender ( 1 ) book ( 1 ) bottomsheet ( 1 ) break ( 1 ) broadcast ( 1 ) browser ( 1 ) bubbles ( 1 ) bug ( 1 ) build ( 1 ) buildcontext ( 1 ) buildnumber ( 1 ) bundle ( 1 ) button ( 1 ) bytecode ( 1 ) cache ( 1 ) camera2 ( 1 ) cameramanager ( 1 ) cd ( 1 ) chrome ( 1 ) ci ( 1 ) circle ( 1 ) clean ( 1 ) clean architecture ( 1 ) cli ( 1 ) clip ( 1 ) clipboard ( 1 ) cloud ide ( 1 ) cmdlet ( 1 ) code ( 1 ) coding test ( 1 ) command ( 1 ) comparator ( 1 ) complexity ( 1 ) concurrency ( 1 ) conditional ( 1 ) const ( 1 ) constraint ( 1 ) constraintlayout ( 1 ) controlc ( 1 ) controlv ( 1 ) converter ( 1 ) copy ( 1 ) copy project ( 1 ) coupling ( 1 ) coverage ( 1 ) cp ( 1 ) css ( 1 ) cupertino ( 1 ) cursor ( 1 ) cv ( 1 ) data class ( 1 ) data structure ( 1 ) dataBinding ( 1 ) database ( 1 ) debounce ( 1 ) decompile ( 1 ) delegate ( 1 ) deno ( 1 ) design pattern ( 1 ) development ( 1 ) device ( 1 ) di ( 1 ) dialog ( 1 ) dio ( 1 ) drawable ( 1 ) drug ( 1 ) emmet ( 1 ) encoding ( 1 ) english ( 1 ) entries ( 1 ) environment ( 1 ) equality ( 1 ) equatable ( 1 ) euc-kr ( 1 ) euckr ( 1 ) exit ( 1 ) expand ( 1 ) expanded ( 1 ) export ( 1 ) extension method ( 1 ) facade ( 1 ) fake ( 1 ) field ( 1 ) figma ( 1 ) final ( 1 ) fixed ( 1 ) flutter pub ( 1 ) flutter web ( 1 ) flutter_inappwebview ( 1 ) flutter_test ( 1 ) flutterflow ( 1 ) fold ( 1 ) fonts ( 1 ) form ( 1 ) frame ( 1 ) future ( 1 ) gestureDetector ( 1 ) gestureRecognizer ( 1 ) gesturearena ( 1 ) get-command ( 1 ) get_cli ( 1 ) getbuilder ( 1 ) getx단점 ( 1 ) gitignore ( 1 ) glut ( 1 ) google fonts ( 1 ) gopath ( 1 ) goto ( 1 ) gradient ( 1 ) graphics ( 1 ) gvim ( 1 ) hackaton ( 1 ) hash ( 1 ) hashmap ( 1 ) hot reload ( 1 ) how to ( 1 ) html ( 1 ) i18n ( 1 ) icon ( 1 ) id ( 1 ) impeller ( 1 ) implementation ( 1 ) import ( 1 ) indicator ( 1 ) inkwell ( 1 ) interrupt ( 1 ) intl ( 1 ) introduction ( 1 ) io ( 1 ) isar ( 1 ) iterable ( 1 ) iteration ( 1 ) javascript ( 1 ) julia ( 1 ) juno ( 1 ) jupyter ( 1 ) kakaomap ( 1 ) keytool ( 1 ) korean ( 1 ) kotlin syntax ( 1 ) l10n ( 1 ) lambda ( 1 ) language ( 1 ) layer ( 1 ) layout ( 1 ) lineageOS ( 1 ) localkey ( 1 ) localtoglobal ( 1 ) long list ( 1 ) ls ( 1 ) mac osx ( 1 ) markdown ( 1 ) markup ( 1 ) material ( 1 ) method ( 1 ) microtask ( 1 ) migrate ( 1 ) mintlify ( 1 ) mock ( 1 ) module ( 1 ) monitor ( 1 ) moor ( 1 ) mouse ( 1 ) mouseregion ( 1 ) multiplatform ( 1 ) multiset ( 1 ) multithread ( 1 ) mutable ( 1 ) mvvm ( 1 ) new ( 1 ) node ( 1 ) nodejs ( 1 ) nosuchmethod ( 1 ) null-safety ( 1 ) numberformat ( 1 ) nvim ( 1 ) object ( 1 ) objectbox ( 1 ) objectkey ( 1 ) obx ( 1 ) online ide ( 1 ) operator ( 1 ) orientation ( 1 ) parabeac ( 1 ) parse ( 1 ) paste ( 1 ) path ( 1 ) pattern ( 1 ) pitfall ( 1 ) play store ( 1 ) pod ( 1 ) podfile ( 1 ) pointer ( 1 ) pointers ( 1 ) powershell ( 1 ) private ( 1 ) programming ( 1 ) pull to refresh ( 1 ) puzzle ( 1 ) pycharm ( 1 ) realitykit ( 1 ) recursion ( 1 ) reduce ( 1 ) reference ( 1 ) regex ( 1 ) regular expression ( 1 ) release note ( 1 ) renderbox ( 1 ) renderobject ( 1 ) repl ( 1 ) repository ( 1 ) response ( 1 ) rm ( 1 ) rotue ( 1 ) round ( 1 ) run ( 1 ) scope ( 1 ) scroll ( 1 ) search ( 1 ) server ( 1 ) serverless ( 1 ) service ( 1 ) sharp ( 1 ) singlerepo ( 1 ) singleton ( 1 ) sketch ( 1 ) sliver ( 1 ) sliverlist ( 1 ) snippets ( 1 ) sogae ( 1 ) sorting ( 1 ) source ( 1 ) sparse ( 1 ) sparse array ( 1 ) spec ( 1 ) split ( 1 ) sqflite ( 1 ) sqlite ( 1 ) sqrt decomposition ( 1 ) stateful ( 1 ) statefulwidget ( 1 ) step ( 1 ) stepper ( 1 ) string ( 1 ) stringbuffer ( 1 ) stringbuilder ( 1 ) studio ( 1 ) study ( 1 ) sub-directory ( 1 ) svn ( 1 ) swiftui ( 1 ) swipe to refresh ( 1 ) system_alert_window ( 1 ) system_cache ( 1 ) systemnavigator ( 1 ) tail recursion ( 1 ) tailrec ( 1 ) tap test ( 1 ) text ( 1 ) texteditingcontroller ( 1 ) textfield ( 1 ) texttheme ( 1 ) themedata ( 1 ) then ( 1 ) thread ( 1 ) throttle ( 1 ) time ( 1 ) tool ( 1 ) tools ( 1 ) tooltip ( 1 ) ts ( 1 ) tutorial ( 1 ) typescript ( 1 ) ui ( 1 ) unittest ( 1 ) update ( 1 ) usb ( 1 ) utf8 ( 1 ) ux ( 1 ) valuekey ( 1 ) variable ( 1 ) vector ( 1 ) versioncode ( 1 ) very_good ( 1 ) view ( 1 ) vim plugin ( 1 ) vimrc ( 1 ) virtualenv ( 1 ) wasm ( 1 ) web app ( 1 ) webview_flutter ( 1 ) while ( 1 ) widget tree ( 1 ) window ( 1 ) wsl ( 1 ) yield ( 1 ) 강의 ( 1 ) 개발 ( 1 ) 개발 공부 ( 1 ) 공부법 ( 1 ) 그래픽스 ( 1 ) 꼬리재귀 ( 1 ) 꿀팁 ( 1 ) 데노 ( 1 ) 두줄 ( 1 ) 디노 ( 1 ) 번역 ( 1 ) 블록 ( 1 ) 상태관리 ( 1 ) 실험 ( 1 ) 안드로이드 ( 1 ) 안드로이드프로젝트 ( 1 ) 안드로이드프로젝트복사 ( 1 ) 어이없는 ( 1 ) 조건부 임포트 ( 1 ) 주절주절분노조절실패의식으흐름 ( 1 ) 패키지 ( 1 ) 프로젝트복사 ( 1 ) 플러그인 ( 1 )