[Dart] Asynchronous programming: futures, async, await

jaehee kim·2021년 5월 23일
1

Dart

목록 보기
5/7
post-thumbnail

Asynchronous programming: futures, async, await

Why asynchronous code matters

Asynchronous 작업은 다른 작업이 완료될 때까지 기다리는 동안 프로그램이 작업을 완료할 수 있습니다. 일반적으로 다음과 같은 작업을 합니다.

  • network를 통해 데이터 가져오기
  • database에 쓰기
  • file에서 데이터 읽기
    Dart에서 asynchronous 작업을 하기위해서 Future class 와 async, await keyword를 사용합니다.

Example: Incorrectly using an asynchronous function

String createOrderMessage() {
  var order = fetchUserOrder();
  return 'Your order is: $order';
}

Future<String> fetchUserOrder() =>
    // Imagine that this function is more complex and slow.
    Future.delayed(
      Duration(seconds: 2),
      () => 'Large Latte',
    );

void main() {
  print(createOrderMessage());
}

// Console 출력 결과
Your order is: Instance of '_Future<String>'
  • fetchUserOrder() 는 asynchronous function 입니다. 2초 후에 Large Latte를 return 합니다.
  • order를 받기 위해서 createOrderMessage()fetchUserOrder() 를 호출해야하고 완료될때까지 기다려야 합니다.
  • createOrderMessage()fetchUserOrder() 가 완료되는 것을 기다리지 않았기 때문에 값을 받아오지 못했습니다.
  • 대신 createOrderMessage() 는 uncompleted future 를 받았습니다.

Key terms

  • synchronous operation : synchronous 작업은 작업이 완료될 때까지 다른 작업들을 중단시킵니다.
  • synchronous function : synchronous 함수는 오직 synchronous 작업만 수행합니다.
  • asynchronous operation : 일단 시작되면, asynchronous 작업은 작업이 완료되기 전에 다른 작업을 수행할 수 있습니다.
  • asynchronous function : asynchronous 함수는 하나 이상의 asynchronous 작업을 수행하고 synchronous 작업도 수행할 수 있습니다.

What is a future?

future 는 asynchronous 동작의 결과이고 2 가지의 state를 가집니다. uncompleted, completed.

  • uncompleted : asynchronous 함수를 호출했을 때, uncompleted future를 return 합니다. 이 future는 asynchronous이 완료되거나 error가 발생하는 것을 기다립니다.
  • completed : 만약 asynchronous 작업이 성공하면 future는 값과 함께 완료되고, 아니면 error와 함께 완료됩니다.
  • type Future<T> 의 future는 type T의 값과 함께 완료됩니다.
Future<void> fetchUserOrder() {
  // Imagine that this function is fetching user info from another service or database.
  return Future.delayed(Duration(seconds: 2), () => print('Large Latte'));
}

void main() {
  fetchUserOrder();
  print('Fetching user order...');
}
// Console 출력 결과
Fetching user order...
Large Latte
Future<void> fetchUserOrder() {
// Imagine that this function is fetching user info but encounters a bug
  return Future.delayed(Duration(seconds: 2),
      () => throw Exception('Logout failed: user ID is invalid'));
}

void main() {
  fetchUserOrder();
  print('Fetching user order...');
}
// Console 출력 결과
Fetching user order...
Uncaught Error: Exception: Logout failed: user ID is invalid

Working with futures: async and await

async, await keyword는 asynchronous 함수를 정의하고 그 결과를 사용하는 선언적인 방법을 제공합니다.

  • async 함수를 정의하기 위해서 async 를 함수의 body 앞에 추가합니다.
  • await keyword는 오직 async 함수에서만 동작합니다.
Future<String> createOrderMessage() async {
  var order = await fetchUserOrder();
  return 'Your order is: $order';
}

Future<String> fetchUserOrder() =>
    // Imagine that this function is
    // more complex and slow.
    Future.delayed(
      Duration(seconds: 2),
      () => 'Large Latte',
    );

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

Key terms

  • async : asynchronous라는 것을 표시하기 위해서 async keyword를 함수의 body 앞에 추가합니다.
  • async function : async 함수는 async keyword가 표시된 함수입니다.
  • await : asynchronous 표현식의 완료된 결과를 얻기 위해 await keyword를 사용합니다. await keyword는 오직 async 함수에서만 동작합니다.

Execution flow with async and await

async 함수는 첫번째 await keyword 전까지는 synchronous하게 동작합니다.

Future<void> printOrderMessage() async {
  print('Awaiting user order...');
  var order = await fetchUserOrder();
  print('Your order is: $order');
}

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

Future<void> main() async {
  countSeconds(4);
  await printOrderMessage();
}

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

// Console 출력 결과
Awaiting user order...
1
2
3
4
Your order is: Large Latte

Handling errors

async 함수에서 error를 처리하기 위해 try-catch 를 사용합니다.

Future<void> printOrderMessage() async {
  try {
    var order = await fetchUserOrder();
    print('Awaiting user order...');
    print(order);
  } catch (err) {
    print('Caught error: $err');
  }
}

Future<String> fetchUserOrder() {
  // Imagine that this function is more complex.
  var str = Future.delayed(
      Duration(seconds: 4),
      () => throw 'Cannot locate user order');
  return str;
}

Future<void> main() async {
  await printOrderMessage();
}


// Console 출력 결과
Caught error: Cannot locate user order






Reference

[Asynchronous programming: futures, async, await]

0개의 댓글