Await future for a specific time

17,099

Solution 1

You can use Future.any constructor to make a race condition

final result = await Future.any([
  Future.value(42),
  Future.delayed(const Duration(seconds: 3))
]);

You can also use Future.timout method

final result = await Future.value(42).timeout(const Duration(seconds: 3));

Solution 2

You can do it very easily

try {
       var response = await Http.get("YourUrl").timeout(const Duration(seconds: 3));
       if(response.statusCode == 200){
          print("Success");
       }else{
          print("Something wrong");
       }
 } on TimeoutException catch (e) {
     print('Timeout');
 } on Error catch (e) {
     print('Error: $e');
 }

This example sets timeout to 3 second. If it has been 3 seconds and no response received, it will throw TimeoutException

Import this :

import 'package:http/http.dart' as Http;
import 'dart:async';

Solution 3

Future.any([asyncfunc, ...])

Here's an example of using Remi's Future.any solution where the future that returns first, will be used. The other is discarded.

So, the first future is your data-gathering/slow function and the other is a fallback when your call is taking too long.

    dynamic result = await Future.any([
      getData(fakeDelay: seconds), // ← hope this returns first
      timeoutAfter(sec: timeout, onTimeout: () => 'Timed Out!', ) // ← waited too long, do this
    ]);

Example in Flutter Page

Here's a copy/paste example for a Flutter page:

(look at your debug/run output window for messages)

import 'package:flutter/material.dart';

class FutureTimeoutPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Future or Timeout Page'),
      ),
      body: FutureAnyExample(),
    );
  }
}

class FutureAnyExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text('Complete before timeout or timeout:'),
        SizedBox(height: 30,),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            ElevatedButton(onPressed: () => getDataOrTimeout(seconds: 1, timeout: 3),
                child: Text('In Time')),
            ElevatedButton(onPressed: () => getDataOrTimeout(seconds: 5, timeout: 3),
                child: Text('Too Slow'))
          ],
        )
      ],
    );
  }

  Future<void> getDataOrTimeout({int seconds, int timeout}) async {
    /// In Future.any, put as many async functions as you need.
    /// Whichever completes first, will be returned. All others are discarded
    dynamic result = await Future.any([
      getData(fakeDelay: seconds), // ← hope this returns first
      timeoutAfter(sec: timeout, onTimeout: () => 'Timed Out!', ) // ← waited too long, do this
    ]);

    print(result);
  }

  /// Mock of a long-running operation like getting DB data, or API call
  Future<String> getData({int fakeDelay}) async {
    return Future.delayed(Duration(seconds: fakeDelay), () => 'Data returned!');
  }

  /// Do this in case my long-running op takes too long
  /// Can run a function or just return some message
  Future<dynamic> timeoutAfter({int sec, Function() onTimeout}) async {
    return Future.delayed(Duration(seconds: sec), onTimeout);
  }
}
Share:
17,099

Related videos on Youtube

Pushan Gupta
Author by

Pushan Gupta

Updated on June 19, 2021

Comments

  • Pushan Gupta
    Pushan Gupta almost 3 years

    How would you wait for future response for a specific amount of time?

    Say, we make a http post request and await for its response before we close the http request, but, we wait for only 3 secs, else we close the request.

    How would you achieve that?

    Something like

    Future makePostReq() async{
      .... 
    
      await http response for 3 secs
    
      .... 
    
     if(response) {
      ... Do something with it
     }
    
     Http.close
    
    } 
    
  • Pushan Gupta
    Pushan Gupta over 5 years
    Will give it a shot. Whats the use of 42?
  • Giacomo M
    Giacomo M over 4 years
    @RémiRousselet sorry to answer to an old thopic: whats the difference between the two solutions? are they still viable?
  • ThinkDigital
    ThinkDigital over 4 years
    @GiacomoM The first one basically tries to resolve 2 futures and returns the one that finishes first. The second one starts a timer and if the future hasn't completed by then, it throws, or if you include an onTimeout function, it'll return that value instead. I'd use the second one, since it was designed for this purpose specifically, but they both work equally well.
  • Giacomo M
    Giacomo M over 4 years
    @ThinkDigital thank you. In this specific example, what returns the const Duration statement? Just a Duration variable? How can I check if my promise got executed or not?
  • ThinkDigital
    ThinkDigital over 4 years
    @GiacomoM yes, you can tell by your return value. Whichever finishes first returns first. The other future will complete, but it&#39;s result will be discarded since you&#39;re using a timeout. This is important just in case this future has side effects like Initializing a class or something. Even if a future&#39;s result is discarded, the future was still run. Think of it like 2 people running a race. The second one still completes the race, but the first one is declared the winner regardless of when or if the second one finished or not
  • Giacomo M
    Giacomo M over 4 years
    @ThinkDigital thank you. In this specific example, what returns the const Duration statement? Just a Duration variable?
  • ThinkDigital
    ThinkDigital over 4 years
    Did you ask this question twice accidentally?
  • Giacomo M
    Giacomo M over 4 years
    @ThinkDigital no, I did not understand exactly in this specific example what returns the statement const Duration(seconds: 3)
  • ThinkDigital
    ThinkDigital over 4 years
    I don't know what you mean by what returns it. You put in what you want. It's your timeout. If you want it to wait for only 10 seconds before you do something else, that's what you put there.
  • Leslie Godwin
    Leslie Godwin over 4 years
    42 is the answer to the big question; the one about the meaning of life, the universe, and everything, so, it's like a very important Future. Well as far as Douglas Adams was concerned.
  • Ray Coder
    Ray Coder about 4 years
    i got error Error: 'TimeoutException' isn't a type. on TimeoutException catch (e) {
  • M4X_
    M4X_ almost 4 years
    you need to add import 'dart:async';