dart:async menyediakan fitur inti pemrograman asinkron Dart: Future, Stream.
- Penggunaan
Future / Streamtidak selalu perlu mengimpor dart:async secara manual, karena sudah diekspor oleh dart:core;- 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
asyncmengembalikan Future; awaitmenunggu Future selesai, menahan eksekusi kode saat ini hingga hasil diterima;- Gunakan
try-catchuntuk 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
- Pembacaan file, data urutan terbatas → gunakan
await for - Peristiwa UI, pesan dorongan berkelanjutan dan aliran tanpa batas → gunakan
.listen() - Setelah await for dijalankan, akan terus menunggu hingga aliran selesai; aliran peristiwa tanpa batas dapat membuat kode terhenti
Pustaka dart:async