Jak mogę „spać” w programie Dart

110

Lubię symulować asynchroniczne wywołanie usługi internetowej w mojej aplikacji Dart do testowania. Aby zasymulować losowość tych próbnych wywołań odpowiadających (prawdopodobnie nie w kolejności), chciałbym zaprogramować moje makiety tak, aby czekały (spały) przez określony czas, zanim zwrócą „Przyszłość”.

Jak mogę to zrobić?

Vinnie
źródło

Odpowiedzi:

117

Możesz także użyć fabryki Future.delayed, aby zakończyć przyszłość po opóźnieniu. Oto przykład dwóch funkcji, które zwracają ciąg znaków asynchronicznie po opóźnieniu:

import 'dart:async';

Future sleep1() {
  return new Future.delayed(const Duration(seconds: 1), () => "1");
}

Future sleep2() {
  return new Future.delayed(const Duration(seconds: 2), () => "2");
}
Shailen Tuli
źródło
9
Jaki jest cel () => "1"?
Daksh Gargas
2
Chyba nie ma sensu, to tylko symbol zastępczy do wykonywania obliczeń
Anil8753
1
Aby spać w aplikacji z tymi funkcjami, musisz użyć await:await sleep1();
Slot
75

Edycja 2019:

W kodzie asynchronicznym

await Future.delayed(Duration(seconds: 1));

W kodzie synchronizacji

import 'dart:io';

sleep(Duration(seconds:1));

Uwaga: Spowoduje to zablokowanie całego procesu (izolację), więc inne funkcje asynchroniczne nie będą przetwarzane. Nie jest również dostępny w Internecie, ponieważ JavaScript jest tak naprawdę tylko asynchroniczny.

Timmmm
źródło
Jaka jest różnica między nimi dwoma (sleep vs Future.delayed)? Co dzieje się za kulisami w obu scenariuszach?
Tomas Baran
3
sleep()całkowicie blokuje cały izolat. Żaden kod Dart w ogóle nie będzie działał podczas snu. Prawdopodobnie kompiluje się do czegoś podobnego do C ++ std::this_thread::sleep_for. Future.delayed()planuje późniejsze wznowienie funkcji asynchronicznej, ale następnie zwraca sterowanie do pętli zdarzeń Dart, aby inne funkcje asynchroniczne mogły nadal działać.
Timmmm
68

Nie zawsze jest to to, czego chcesz (czasami chcesz Future.delayed), ale jeśli naprawdę chcesz spać w aplikacji wiersza poleceń Dart, możesz użyć dart: io's sleep():

import 'dart:io';

main() {
  sleep(const Duration(seconds:1));
}
Seth Ladd
źródło
Dobry! Niestety te informacje są trudne do znalezienia na oficjalnej stronie.
Timur Fayzrakhmanov
12
Biblioteka „dart: io” nie jest dostępna, jeśli tworzysz aplikację internetową
adeel41
5
From docs: używaj tego ostrożnie, ponieważ żadne operacje asynchroniczne nie mogą być przetwarzane w izolacji, gdy jest ono blokowane w wywołaniu [sleep].
bartektartanus
2
UWAGA : To jest synchroniczne !!! Zatrzyma główny wątek! (Jestem takim głupcem, że zrobiłem await sleep()i spodziewam się innych zadań podczas snu :(
ch271828n
1
Jaka jest różnica między nimi dwoma (sleep vs Future.delayed)? Co dzieje się za kulisami w obu scenariuszach?
Tomas Baran
25

Odkryłem, że istnieje kilka implementacji w Dart, aby wykonać opóźnienie kodu:

new Future.delayed(const Duration(seconds: 1)); //recommend

new Timer(const Duration(seconds: 1), ()=>print("1 second later."));

sleep(const Duration(seconds: 1)); //import 'dart:io';

new Stream.periodic(const Duration(seconds: 1), (_) => print("1 second later.")).first.then((_)=>print("Also 1 second later."));
//new Stream.periodic(const Duration(seconds: 1)).first.then((_)=>print("Also 1 second later."));
SpkingR
źródło
17

Dla składni Dart 2+, w kontekście funkcji asynchronicznej:

import 'package:meta/meta.dart'; //for @required annotation

void main() async {
  void justWait({@required int numberOfSeconds}) async {
    await Future.delayed(Duration(seconds: numberOfSeconds));
  }

  await justWait(numberOfSeconds: 5);
} 
Bono Lv
źródło
3

To przydatna makieta, która może przyjmować opcjonalny parametr, aby mockować błąd:

  Future _mockService([dynamic error]) {
    return new Future.delayed(const Duration(seconds: 2), () {
      if (error != null) {
        throw error;
      }
    });
  }

Możesz go używać w ten sposób:

  await _mockService(new Exception('network error'));
Jannie Theunissen
źródło
-2

Musiałem również poczekać na zakończenie usługi podczas testu jednostkowego. Zaimplementowałem w ten sposób:

void main()
{
    test('Send packages using isolate', () async {
        await SendingService().execute();
    });
    // Loop to the amount of time the service will take to complete
    for( int seconds = 0; seconds < 10; seconds++ ) {
        test('Waiting 1 second...', () {
            sleep(const Duration(seconds:1));
        } );
    }
}
...
class SendingService {
    Isolate _isolate;
    Future execute() async {
        ...
        final MyMessage msg = new MyMessage(...);
        ...
        Isolate.spawn(_send, msg)
            .then<Null>((Isolate isolate) => _isolate = isolate);
    }
    static void _send(MyMessage msg) {
        final IMyApi api = new IMyApi();
        api.send(msg.data)
            .then((ignored) {
                ...
            })
            .catchError((e) {
                ...
            } );
    }
}
Luciano
źródło
To nie jest dobre, ponieważ zwykle nie wiesz, ile czasu zajmie ukończenie usługi.
mcfly