Wie kann ich ein Dart-Programm "schlafen"?

90

Ich möchte einen asynchronen Webdienstaufruf in meiner Dart-Anwendung zum Testen simulieren. Um die Zufälligkeit dieser Scheinanrufe zu simulieren, die reagieren (möglicherweise nicht in der richtigen Reihenfolge), möchte ich meine Mocks so programmieren, dass sie eine bestimmte Zeit warten (schlafen), bevor sie die 'Zukunft' zurückgeben.

Wie kann ich das machen?

Vinnie
quelle

Antworten:

101

Sie können auch die Future.delayed-Factory verwenden, um eine Zukunft nach einer Verzögerung abzuschließen. Hier ist ein Beispiel für zwei Funktionen, die einen String nach einer Verzögerung asynchron zurückgeben:

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
quelle
7
Was ist der Zweck von () => "1"?
Daksh Gargas
2
Ich denke, es nützt nichts, es ist nur ein Platzhalter, um Ihre Berechnungen durchzuführen
Anil8753
63

Es ist nicht immer das, was Sie wollen (manchmal wollen Sie es Future.delayed), aber wenn Sie wirklich in Ihrer Dart-Befehlszeilen-App schlafen möchten, können Sie dart: io's verwenden sleep():

import 'dart:io';

main() {
  sleep(const Duration(seconds:1));
}
Seth Ladd
quelle
Gut! Leider sind diese Informationen auf der offiziellen Website schwer zu finden.
Timur Fayzrakhmanov
11
Die Bibliothek 'dart: io' ist nicht verfügbar, wenn Sie eine Webanwendung erstellen
adeel41
4
Aus Dokumenten: Gehen Sie vorsichtig damit um, da in einem Isolat keine asynchronen Vorgänge verarbeitet werden können , während es in einem [Schlaf] -Aufruf blockiert ist.
Bartektartanus
Dadurch wird der Hauptthread gestoppt. Verwenden Sie Future.delayed für Simulationen.
Siloé Bezerra Bispo
1
Was ist der Unterschied zwischen den beiden (Schlaf gegen Future.delayed)? Was ist in beiden Szenarien hinter den Kulissen los?
Tomas Baran
41

Ausgabe 2019:

Im asynchronen Code

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

Im Synchronisierungscode

import 'dart:io';

sleep(Duration(seconds:1));

Hinweis: Dies blockiert den gesamten Prozess (isolieren), sodass andere asynchrone Funktionen nicht verarbeitet werden. Es ist auch nicht im Web verfügbar, da Javascript wirklich nur asynchron ist.

Timmmm
quelle
Was ist der Unterschied zwischen den beiden (Schlaf gegen Future.delayed)? Was ist in beiden Szenarien hinter den Kulissen los?
Tomas Baran
2
sleep()blockiert das gesamte Isolat vollständig. Während des Schlafens wird überhaupt kein Dart-Code ausgeführt. Es wird wahrscheinlich zu etwas wie C ++ kompiliert std::this_thread::sleep_for. Future.delayed()plant, dass die asynchrone Funktion später fortgesetzt wird, gibt dann jedoch die Steuerung an die Dart-Ereignisschleife zurück, damit andere asynchrone Funktionen weiterhin ausgeführt werden können.
Timmmm
24

Ich habe festgestellt, dass es in Dart mehrere Implementierungen gibt, um die Ausführung der Codeverzögerung durchzuführen:

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
quelle
16

Für die Dart 2+ -Syntax in einem asynchronen Funktionskontext:

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
quelle
3

Dies ist ein nützliches Modell, das einen optionalen Parameter verwenden kann, um einen Fehler zu verspotten:

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

Sie können es so verwenden:

  await _mockService(new Exception('network error'));
Jannie Theunissen
quelle
-2

Ich musste auch warten, bis ein Service während eines Komponententests abgeschlossen war. Ich habe folgendes implementiert:

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
quelle
Dies ist nicht gut, da Sie normalerweise nicht wissen, wie viel Zeit Ihr Service benötigt, um fertig zu werden.
Mcfly