# Futures

JS의 Promise와 유사하다

  • 선물상자와 비슷하다

image-20220218102840869

  • 상자를 어떻게 만들것인가?

  • 열어서 어떻게 할것인가? 가 관건이다

  • dart는 single thread와 event loop를 사용한다.

  • 많은 경우에 future를 직접 생성하지 않는다. 왜냐면 라이브러리들이 이미 포함하고 있기 때문

    myFuture  = http.get('http://example.com')
        
    myFuture = SharedPreferences.getInstance
    
    1
    2
    3
  • 그렇지만 future의 constructor도 있다.

    import 'dart:async';
    
    void main(){
        final myFuture = Future((){
            return 12;
        });
    }
    
    1
    2
    3
    4
    5
    6
    7
  • future의 값을 지정할 수 있는 Future.value constructor를 사용할 수 있다. 캐시된 데이터를 사용할 때 유용하다.

    final myFuture = Future.value(12);
    
    1
  • error를 미리 지정할 수 있기도 하다.

    final myFuture = Future.error();
    
    1
  • 가장많이 사용하는건 Future.delayed()다. 네트워킨과 스피너 Testing을 위해 많이 사용한다.

    final myFuture = Future.delayed(
    	Duration(seconds:5),
    	()=>12,
    );
    
    1
    2
    3
    4
  • Future Chaining은 이런식으로 일어난다.

    final myFuture = _fetchNameForId(12)
        .then((name) => _fetchCountForName(name))
        .then((count) => print(count))
    
    1
    2
    3

    return 타입이 다르더라도 chaining이 가능하다

  • 한편, 에러로 끝났을때의 콜백도 지정해줘야 한다.

    import 'dart:async';
    
    void main(){
        Future<int>.delayed(
        Duration(seconds:3),
        (){throw 'Error!';})
            .then((value){
                print(value);
            })
            .catchError(
        (err){
            print('Caught $err')
        })
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    dart에서는 catchError를 사용하게 된다.

  • 두개다 끝나고 난뒤에 사용하는 whenComplete도 있다. try-catch문의 finally와 비슷하다.

# FutureBuilder

위에 과정이 복잡하다면 FutureBuilder로 할 수 있다.

Future와 Builder를 준다면 Future가 완료되면 알아서 children을 만들어 준다.

builder메소드에 context와 snapshot(Future의 현재 상태)를 보고 결정할 수 있다.

class MyWidget extends StatelessWidget{
    
    Widget build(BuildContext context){
        return FutureBuilder<String>(
        future: _fetchNetworkData(),
        builder:(context, snapshot){
            if(snapshot.hasError){
                return Text("ha")
            }
        })
    }
}
1
2
3
4
5
6
7
8
9
10
11
12