¿Cómo puedo "dormir" un programa de Dart?

102

Me gusta simular una llamada de servicio web asincrónica en mi aplicación Dart para realizar pruebas. Para simular la aleatoriedad de estas llamadas simuladas respondiendo (posiblemente fuera de orden), me gustaría programar mis simulaciones para esperar (dormir) durante un cierto período de tiempo antes de devolver el 'Futuro'.

¿Cómo puedo hacer esto?

Vinnie
fuente

Respuestas:

111

También puede utilizar la fábrica Future.delayed para completar un futuro después de un retraso. A continuación, se muestra un ejemplo de dos funciones que devuelven una cadena de forma asincrónica después de un retraso:

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
fuente
8
¿Cuál es el propósito de () => "1"?
Daksh Gargas
2
Supongo que no sirve de nada, es solo un marcador de posición para hacer sus cálculos
Anil8753
Para dormir su aplicación con estas funciones, debe usar await:await sleep1();
Slot hace
67

No siempre es lo que quieres (a veces quieres Future.delayed), pero si realmente quieres dormir en tu aplicación de línea de comandos Dart, puedes usar dart: io's sleep():

import 'dart:io';

main() {
  sleep(const Duration(seconds:1));
}
Seth Ladd
fuente
¡Bueno! Desafortunadamente, esta información es difícil de encontrar en el sitio oficial.
Timur Fayzrakhmanov
11
La biblioteca 'dart: io' no está disponible si está creando una aplicación web
adeel41
4
De los documentos: Use esto con cuidado, ya que no se pueden procesar operaciones asincrónicas de forma aislada mientras está bloqueada en una llamada [de suspensión].
bartektartanus
1
ADVERTENCIA : ¡¡¡Esto es sincrónico !!! ¡Detendrá el hilo principal! (Soy tan tonto que lo hice await sleep()y espero que los otros trabajos se ejecuten mientras duerme :(
ch271828n
1
¿Cuál es la diferencia entre ellos dos (dormir frente a futuro retrasado)? ¿Qué sucede detrás de escena en ambos escenarios?
Tomas Baran
63

Edición 2019:

En código asincrónico

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

En código de sincronización

import 'dart:io';

sleep(Duration(seconds:1));

Nota: Esto bloquea todo el proceso (aislar), por lo que no se procesarán otras funciones asíncronas. Tampoco está disponible en la web porque Javascript es solo asíncrono.

Timmmm
fuente
¿Cuál es la diferencia entre ellos dos (dormir frente a futuro retrasado)? ¿Qué sucede detrás de escena en ambos escenarios?
Tomas Baran
3
sleep()bloquea completamente todo el aislamiento. No se ejecutará ningún código de Dart mientras esté inactivo. Probablemente se compile en algo parecido a C ++ std::this_thread::sleep_for. Future.delayed()programa la función asíncrona para que se reanude más tarde, pero luego devuelve el control al bucle de eventos de Dart para que otras funciones asíncronas puedan continuar ejecutándose.
Timmmm
24

Descubrí que hay varias implementaciones en Dart para hacer que el código demore la ejecución:

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

Para la sintaxis de Dart 2+, en un contexto de función asíncrona:

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

Este es un simulacro útil que puede tomar un parámetro opcional para simular un error:

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

Puedes usarlo así:

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

También necesitaba esperar a que se completara un servicio durante una prueba unitaria. Implementé de esta manera:

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
fuente
Esto no es bueno ya que normalmente no sabe cuánto tiempo tarda su servicio en finalizar.
mcfly