Pustaka dart:async

dart:async menyediakan fitur inti pemrograman asinkron Dart: Future, Stream.

  1. Penggunaan Future / Stream tidak selalu perlu mengimpor dart:async secara manual, karena sudah diekspor oleh dart:core;
  2. Jika ingin menggunakan tipe seperti StreamController, StreamSubscription, ParallelWaitError, Anda perlu melakukan impor eksplisit:
import 'dart:async';Code language: JavaScript (javascript)

Dua konsep utama:

  • Future: Mewakili hasil asinkron sekali saja (hanya akan menghasilkan satu nilai atau satu kesalahan di waktu mendatang)
  • Stream: Mewakili rangkaian data asinkron berkelanjutan (menghasilkan banyak data secara terus-menerus, mirip aliran peristiwa)

Future

1. async / await

Sangat disarankan, tingkat keterbacaan lebih baik dibanding pemanggilan berantai .then()

  • Fungsi yang ditandai async mengembalikan Future;
  • await menunggu Future selesai, menahan eksekusi kode saat ini hingga hasil diterima;
  • Gunakan try-catch untuk menangkap pengecualian asinkron.
// Fungsi async mengembalikan Future
Future<String> findEntryPoint() async => "main.dart";
Future<int> runExecutable(String entry, List args) async => 0;
Future<void> flushThenExit(int code) async {}

// Penulisan await (disarankan)
Future<void> runUsingAsyncAwait() async {
  try {
    var entryPoint = await findEntryPoint();
    var exitCode = await runExecutable(entryPoint, []);
    await flushThenExit(exitCode);
  } catch (e) {
    // Tangkap semua pengecualian
    print("Terjadi kesalahan: $e");
  }
}Code language: JavaScript (javascript)

2. .then() / .catchError() gaya penulisan berantai tradisional

  • .then(): Callback yang dijalankan setelah Future berhasil selesai; mengembalikan Future baru sehingga bisa dirantai terus
  • .catchError(): Menangkap kesalahan; harus dirantai setelah nilai balik then, jika tidak tidak dapat menangkap kesalahan di dalam then
void runUsingFuture() {
  findEntryPoint()
      .then((entryPoint) {
        return runExecutable(entryPoint, []);
      })
      .then(flushThenExit)
      .catchError((e) {
        print("Pengecualian: $e");
      });
}Code language: JavaScript (javascript)

3. Menunggu beberapa Future berjalan bersamaan

① Future.wait()

Menunggu semua tugas selesai dijalankan; jika salah satu Future gagal, seluruh proses langsung dianggap gagal

Future<void> task1() async {}
Future<void> task2() async {}
Future<void> task3() async {}

void testWait() async {
  await Future.wait([
    task1(),
    task2(),
    task3(),
  ]);
  print("Semua tugas telah selesai dieksekusi");
}Code language: JavaScript (javascript)
② List.wait / Record.wait (fitur baru, menangani kesalahan konkurensi dengan detail)

Akan melempar ParallelWaitError, Anda bisa membedakan mana yang berhasil dan mana yang gagal, tanpa saling menghentikan.

Future<int> delete() async => 1;
Future<String> copy() async => "ok";
Future<bool> errorTask() async {
  throw Exception("Tugas gagal");
}

void main() async {
  try {
    // Bentuk daftar
    var results = await [delete(), copy(), errorTask()].wait;
  } on ParallelWaitError<List<Object?>, List<AsyncError?>> catch (e) {
    print(e.values);   // Berhasil berisi nilai, yang gagal bernilai null
    print(e.errors);   // Yang berhasil bernilai null, yang gagal menyimpan informasi kesalahan
  }

  // Bentuk Record tuple: mendukung Future dengan tipe berbeda
  try {
    final (resInt, resStr, resBool) = await (delete(), copy(), errorTask()).wait;
  } on ParallelWaitError<(int?, String?, bool?), (AsyncError?, AsyncError?, AsyncError?)> catch(e) {

  }
}Code language: JavaScript (javascript)

Stream

Stream merepresentasikan rangkaian data asinkron yang berkelanjutan (pembacaan file baris demi baris, peristiwa klik tombol, aliran data jaringan).

Dua cara penggunaan

1: await for perulangan asinkron (ringkas, mirip iterasi sinkron)

Cocok untuk aliran data terbatas; tidak disarankan untuk aliran peristiwa tanpa batas (contoh: klik halaman), karena akan menahan kode selanjutnya.

import 'dart:io';

Future<void> readFileByAwaitFor() async {
  var file = File("config.txt");
  Stream<List<int>> input = file.openRead();
  var lines = input
      .transform(utf8.decoder)
      .transform(const LineSplitter());

  try {
    await for (final line in lines) {
      print("Membaca satu baris: $line");
    }
    print("Pembacaan file selesai");
  } catch (e) {
    print("Kesalahan pembacaan $e");
  }
}Code language: PHP (php)
2 .listen() langganan pendengar (cocok untuk aliran tanpa batas)
inputStream.listen(
  (data) {
    // Callback saat menerima data
  },
  onError: (err) {
    // Terjadi kesalahan
  },
  onDone: () {
    // Aliran selesai ditutup dengan normal
  },
);Code language: JavaScript (javascript)

listen mengembalikan StreamSubscription, Anda bisa memanggil .cancel() untuk membatalkan langganan.

Metode operasi Stream yang sering digunakan

  • Penyaringan: where()
  • Pemotongan: take(), takeWhile()
  • Melewatkan data: skip(), skipWhile()
  • Mendapatkan satu elemen: first, last, single, firstWhere()

Transformasi data Stream dengan transform()

Mengubah tipe data aliran melalui transformer (contoh kasus umum: aliran biner menjadi teks)

var lines = inputStream
    .transform(utf8.decoder)       // List<int> → String
    .transform(const LineSplitter()); // String → teks per barisCode language: JavaScript (javascript)

Saran pilihan: listen() vs await for

  1. Pembacaan file, data urutan terbatas → gunakan await for
  2. Peristiwa UI, pesan dorongan berkelanjutan dan aliran tanpa batas → gunakan .listen()
  3. Setelah await for dijalankan, akan terus menunggu hingga aliran selesai; aliran peristiwa tanpa batas dapat membuat kode terhenti

Pustaka dart:async

Previous:

Tinggalkan Balasan

Alamat email Anda tidak akan dipublikasikan. Ruas yang wajib ditandai *