Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
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
Archives
Today
Total
관리 메뉴

nomad-programmer

[Programming/Dart] 비동기 프로그래밍 : futures, async, await 본문

Programming/Dart

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

scii 2020. 10. 10. 18:35

비동기 코드의 중요성

비동기 작업은 다른 작업들이 비동기 작업이 완료 되는 것을 기다리는 동안 다른 일들을 완성하도록 진행한다.

  • 네트워크에서 데이터 가져오기
  • 데이터베이스 연산
  • 파일에서 데이터 읽기/쓰기
  • 등등...

비동기 작업을 위해 Future 클래스와 async, await 키워드를 사용한다.

Future

Future는 비동기 작업의 결과를 2개의 상태로 표현한다. 상태에는 완성(completed)된 상태와, 미완성(uncompleted) 상태로 나뉜다.

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

미완성 (Uncompleted)

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

완성 (Completed)

비동기 작업이 성공하면, Future는 값을 완성하게 된다. 작업이 실패하면 에러를 완성한다.

값으로 완성

Future의 T타입 값으로 완성된다. 사용가능한 값을 만들지 않는 경우에는 Future 값을 사용한다.

Future<void> getUserOrder() {
  return Future.delayed(
    Duration(seconds: 3),
    () => print('Ice Americano'),
  );
}

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

/* 결과

Fetching user order...
Ice Americano

*/

에러로 완성

비동기 작업이 어떤 이유로 실패하면 에러로 Future가 완성된다.

Future<void> getUserOrder() {
  return Future.delayed(
    Duration(seconds: 3),
    () => throw Exception('Logout failed: user ID is invalid'),
  );
}

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

/* 결과

Fetching user order...
Unhandled exception:
Exception: Logout failed: user ID is invalid
#0      getUserOrder.<anonymous closure> (package:test2/test.dart:4:11)
#1      new Future.delayed.<anonymous closure> (dart:async/future.dart:326:39)
...

*/

async & await

async & await 은 함수를 정의하고 그 결과를 사용하기 위한 선언적인(declarative) 방법을 제공한다.

  • async 함수를 정의하려면 함수 몸체 전에 async를 추가한다.
  • await 키워드는 async 함수에서만 사용할 수 있다.

비동기 main 함수

main() async {}
Dart에서는 타입 추론을 지원하지만, 제품 단계 코드에서는 타입을 지정하는 것이 좋으며 추천한다.
Future<void> main() async {}

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

Future<String> createOrderMessage() async {
  var order = await getUserOrder();
  return 'Your order is: $order';
}

Future<String> getUserOrder() {
  return Future.delayed(
    Duration(seconds: 3),
    () => 'Ice Americano',
  );
}

Future<void> main() async {
  print('Fetching user order...');
  print(await createOrderMessage());
}

/* 결과

Fetching user order...
Your order is: Ice Americano

*/
  • async 키워드를 통해서 createOrderMessage, main 함수가 비동기 함수가 되었다.
  • 비동기문의 완성된 결과를 받기 위해서 await 키워드가 getUserOrder, createOrderMessage에 사용되었다. 즉, Future를 반환하는 함수들을 호출할 때는 await 키워드를 붙인다.

파일 IO 비동기 프로그램 예제 코드

import 'dart:io';

Future<void> createDescriptions(Iterable<String> objects) async {
  for (var object in objects) {
    try {
      File file = new File('$object.txt');
      if (await file.exists()) {
        DateTime modified = await file.lastModified();
        print('File for $object already exists. It was modified on $modified.');
        continue;
      }
      await file.create();
      await file.writeAsString('Start describing $object in this file.');
    } on IOException catch (e) {
      print('cannot create description for $object: $e');
    }
  }
}

Future<void> main() async {
  List<String> fileList = <String>[
    '/Users/method/Desktop/aaa',
    '/Users/method/Desktop/bbb',
  ];
  await createDescriptions(fileList);
}

/* 결과

File for /Users/method/Desktop/aaa already exists. It was modified on 2020-10-10 19:16:47.000.
File for /Users/method/Desktop/bbb already exists. It was modified on 2020-10-10 19:25:27.000.

*/

 

Comments