Bagaimana saya bisa "tidur" program Dart

108

Saya suka mensimulasikan panggilan layanan web asinkron di aplikasi Dart saya untuk pengujian. Untuk mensimulasikan keacakan panggilan tiruan ini yang merespons (mungkin rusak), saya ingin memprogram pengolok saya untuk menunggu (tidur) selama jangka waktu tertentu sebelum mengembalikan 'Masa Depan'.

Bagaimana saya bisa melakukan ini?

Vinnie
sumber

Jawaban:

116

Anda juga dapat menggunakan pabrik Future.delayed untuk menyelesaikan masa depan setelah penundaan. Berikut adalah contoh dari dua fungsi yang mengembalikan string secara asinkron setelah penundaan:

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
sumber
9
Apa tujuan dari () => "1"?
Daksh Gargas
2
Saya kira tidak ada gunanya, ini hanya tempat penampung untuk melakukan
perhitungan
1
Untuk mengaktifkan aplikasi Anda dengan fungsi ini, Anda perlu menggunakan await:await sleep1();
Slot
73

Edisi 2019:

Dalam Kode Async

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

Dalam Kode Sinkronisasi

import 'dart:io';

sleep(Duration(seconds:1));

Catatan: Ini memblokir seluruh proses (mengisolasi), sehingga fungsi asinkron lainnya tidak akan diproses. Ini juga tidak tersedia di web karena Javascript benar-benar hanya asinkron.

Timmmm
sumber
Apa bedanya keduanya (sleep vs Future.delayed)? Apa yang terjadi di balik layar di kedua skenario?
Tomas Baran
3
sleep()benar-benar memblokir seluruh isolat. Tidak ada kode Dart yang akan berjalan sama sekali saat sedang tidur. Ini mungkin dikompilasi ke sesuatu seperti C ++ std::this_thread::sleep_for. Future.delayed()menjadwalkan fungsi asinkron untuk dilanjutkan nanti, tetapi kemudian mengembalikan kontrol ke loop peristiwa Dart sehingga fungsi asinkron lainnya dapat terus berjalan.
Timmmm
68

Tidak selalu itu yang Anda inginkan (terkadang Anda inginkan Future.delayed), tetapi jika Anda benar-benar ingin tidur di aplikasi baris perintah Dart, Anda dapat menggunakan dart: io's sleep():

import 'dart:io';

main() {
  sleep(const Duration(seconds:1));
}
Seth Ladd
sumber
Baik! Sayangnya, informasi ini sulit ditemukan di situs resminya.
Timur Fayzrakhmanov
12
Perpustakaan 'dart: io' tidak tersedia jika Anda membuat aplikasi web
adeel41
5
Dari dokumen: Gunakan ini dengan hati-hati, karena tidak ada operasi asinkron yang dapat diproses secara terpisah saat diblokir dalam panggilan [tidur].
bartektartanus
2
PERINGATAN : Ini sinkron !!! Ini akan menghentikan utas utama! (Saya sangat bodoh bahwa saya melakukan await sleep()dan mengharapkan pekerjaan lain berjalan selama tidur :(
ch271828n
1
Apa bedanya keduanya (sleep vs Future.delayed)? Apa yang terjadi di balik layar di kedua skenario?
Tomas Baran
25

Saya menemukan bahwa ada beberapa implementasi di Dart untuk membuat eksekusi penundaan kode:

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
sumber
17

Untuk sintaks Dart 2+, dalam konteks fungsi asinkron:

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

Ini adalah tiruan berguna yang dapat menggunakan parameter opsional untuk membuat tiruan kesalahan:

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

Anda bisa menggunakannya seperti ini:

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

Saya juga perlu menunggu layanan selesai selama pengujian unit. Saya menerapkan cara ini:

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
sumber
Ini tidak baik karena Anda biasanya tidak tahu berapa lama waktu yang dibutuhkan untuk menyelesaikan layanan.
mcfly