Dart (5) - 비동기 프로그래밍

소밍·2023년 6월 29일
0
post-thumbnail

작업을 하는 가장 작은 유닛 - 스레드
비동기 프로그래밍을 사용하면 cpu 스레드를 효율적으로 사용할 수 있음

Future

  • 미래에 받아올 값
  • Future 키워드를 사용하면 비동기로 프로그래밍할 수 있음
void main(){
 Future<String> name = Future.value('솜');
 Future<int> number = Future.value(1);
 Future<bool> isTrue = Future.value(true);
  
 print('함수시작');
  
 // Future.delayed는 두개의 파라미터 받음
 // 1번 파라미터 : 지연할 기간 Duration
 // 2번 파라미터 : 지연 기간 지난 후 실행할 함수 
 Future.delayed(Duration(seconds:2),(){
    print('2초 끝');
 });
}
void main(){
  addNumbers(1,1);
  addNumbers(2,2);
}

void addNumbers(int number1, int number2){
  print('계산 시작 : $number1 + $number2');
  
  // 서버 시뮬레이션
  Future.delayed(Duration(seconds:2),(){
    print('계산 완료 : $number1 + $number2 = ${number1+number2}');
  });
  
  print('함수 완료');
}


// 계산 시작 : 1 + 1
// 함수 완료
// 계산 시작 : 2 + 2
// 함수 완료
// 계산 완료 : 1 + 1 = 2
// 계산 완료 : 2 + 2 = 4

await

  • await는 Future를 리턴해주는 함수에만 사용할 수 있다.
  • async 키워드를 넣어야 await 사용할 수 있음
  • await을 사용하여 async 코드를 논리적으로 기다릴 수 있다.
  • 기다리는 동안 cpu가 다른 작업을 할 수 있다.
void main(){
  addNumbers(1,1);
}

void addNumbers(int number1, int number2) async {
  print('계산 시작 : $number1 + $number2');
  
  // 서버 시뮬레이션
  await Future.delayed(Duration(seconds:2),(){
    print('계산 완료 : $number1 + $number2 = ${number1+number2}');
  });
  
  print('함수 완료 : $number1 + $number2');
}

// 계산 시작 : 1 + 1
// 계산 완료 : 1 + 1 = 2
// 함수 완료 : 1 + 1

await 해버리면 cpu가 2초동안 기다리며 아무것도 안하는 거 아닌가?- 놉

void main(){
  addNumbers(1,1);
  addNumbers(2,2);
}

void addNumbers(int number1, int number2) async {
  print('계산 시작 : $number1 + $number2');
  
  // 서버 시뮬레이션
  await Future.delayed(Duration(seconds:2),(){
    print('계산 완료 : $number1 + $number2 = ${number1+number2}');
  });
  
  print('함수 완료 : $number1 + $number2');
}

// 계산 시작 : 1 + 1
// 계산 시작 : 2 + 2
// 계산 완료 : 1 + 1 = 2
// 함수 완료 : 1 + 1
// 계산 완료 : 2 + 2 = 4
// 함수 완료 : 2 + 2
void main() async{
  await addNumbers(1,1);
  await addNumbers(2,2);
}

Future<void> addNumbers(int number1, int number2) async {
  print('계산 시작 : $number1 + $number2');
  
  // 서버 시뮬레이션
  await Future.delayed(Duration(seconds:2),(){
    print('계산 완료 : $number1 + $number2 = ${number1+number2}');
  });
  
  print('함수 완료 : $number1 + $number2');
}

// 계산 시작 : 1 + 1
// 계산 완료 : 1 + 1 = 2
// 함수 완료 : 1 + 1
// 계산 시작 : 2 + 2
// 계산 완료 : 2 + 2 = 4
// 함수 완료 : 2 + 2

future을 사용하여 비동기 프로그래밍을 통한 return값을 받기

void main() async{
  final result1 = await addNumbers(1,1);
  final result2 = await addNumbers(2,2);
  
  print('result1: $result1');
  print('result2: $result2');
  print('result1 + result2 = ${result1+result2}');    
}

Future<int> addNumbers(int number1, int number2) async {
  print('계산 시작 : $number1 + $number2');
  
  // 서버 시뮬레이션
  await Future.delayed(Duration(seconds:2),(){
    print('계산 완료 : $number1 + $number2 = ${number1+number2}');
  });
  
  print('함수 완료 : $number1 + $number2');
  
  return number1 + number2;
}

// 계산 시작 : 1 + 1
// 계산 완료 : 1 + 1 = 2
// 함수 완료 : 1 + 1
// 계산 시작 : 2 + 2
// 계산 완료 : 2 + 2 = 4
// 함수 완료 : 2 + 2
// result1: 2
// result2: 4
// result1 + result2 = 6

Stream

  • dart 언어에서 기본적으로 제공하는 기능 아님
    import 'dart:async';

future는 하나의 함수에서 하나의 값만 받아낼 수 있음
-> 여러 순간에 여러번 값을 받아내려면 함수를 여러번 실행해야함

stream에선 데이터가 흐름..? 롸?
stream을 닫을 때까지 반환값을 받을 수 있음

import 'dart:async';

void main(){
  final controller = StreamController();
// controller.stream -> 기본적으로 한번만 리스닝할 수 있는 리소스 생김
// controller.stream.asBroadcastStream(); 여러번 계속 리스닝 하고 싶다면
  final stream = controller.stream.asBroadcastStream();
  
  final streamListener1 = stream.listen((val){
    print('Listener 1 : $val');
  });
  
  final streamListener2 = stream.listen((val){
    print('Listener 2 : $val');
  });
  
  controller.sink.add(1);
  controller.sink.add(2);
  controller.sink.add(3);
}

// Listener 1 : 1
// Listener 2 : 1
// Listener 1 : 2
// Listener 2 : 2
// Listener 1 : 3
// Listener 2 : 3

즉석에서 stream값 변경하는 방법

데이터가 들어오는 순간에 바로 데이터를 변형할 수 있다.

import 'dart:async';

void main() {
  final controller = StreamController();
  final stream = controller.stream.asBroadcastStream();
  
  final streamListener1 = stream.where((val)=> val%2==0).listen((val){
    print('Listener 1 : $val');
  });
  
  final streamListener2 = stream.where((val)=> val%2==1).listen((val){
    print('Listener 2 : $val');
  });
  
  controller.sink.add(1);
  controller.sink.add(2);
  controller.sink.add(3);
  controller.sink.add(4);
  controller.sink.add(5);
}

// Listener 2 : 1
// Listener 1 : 2
// Listener 2 : 3
// Listener 1 : 4
// Listener 2 : 5

yield

일드 실행될 때마다 calculate 함수를 리스닝하고 있는 리스너에다 값을 뿌려줄 수 있음

import 'dart:async';

void main() {
  calculate(2).listen((val){
    print('calculate(2) : $val');
  });
}

Stream<int>calculate(int number) async*{
  for(int i=0; i<5; i++){
    yield i*number; 
  }
}

// calculate(2) : 0
// calculate(2) : 2
// calculate(2) : 4
// calculate(2) : 6
// calculate(2) : 8

일반적인 future관련된 async 함수를 async*로 된 함수에서 사용하는 방법

  • stream 속에서 await 하면 ? 이또한 async로 진행
import 'dart:async';

void main() {
  calculate(2).listen((val){
    print('calculate(2) : $val');
  });
  
    calculate(4).listen((val){
    print('calculate(4) : $val');
  });
}

Stream<int>calculate(int number) async*{
  for(int i=0; i<5; i++){
    yield i*number; 
    
    await Future.delayed(Duration(seconds: 1));
  }
}

// 동시 실행 직접 찍어서 확인하기

Stream을 await하기

yield는 값을 하나하나 순서대로 가져오는데 사용됐지만
yield*을 하게되면 해당되는 스트림의 모든 값을 가져올 때까지 기다림. (값이 다 리턴될때까지) -> future의 await와 비슷한 기능

import 'dart:async';

void main() {
  playAllStream().listen((val){
    print(val);
  });
}

Stream<int> playAllStream() async*{
  yield* calculate(1); // 첫번째 함수의 스트림이 모두 끝나야
  yield* calculate(1000); // 두번째 함수의 스트림이 시작될 것
}

Stream<int>calculate(int number) async*{
  for(int i=0; i<5; i++){
    yield i*number; 
    
    await Future.delayed(Duration(seconds: 1));
  }
}

// 0
// 1
// 2
// 3
// 4
// 0
// 1000
// 2000
// 3000
// 4000
profile
생각이 길면 용기는 사라진다.

0개의 댓글

관련 채용 정보