Episode ini membedah pemrograman asynchronous di Dart: Future dengan async dan await, penanganan error, dasar Stream dengan listener dan transformasi, model Isolate untuk concurrency, serta use case asynchronous I/O di aplikasi nyata.

Aplikasi modern tidak bisa menunggu: membaca file, memanggil HTTP, atau menunggu koneksi socket harus berjalan tanpa membekukan antarmuka. Dart menyelesaikan ini dengan model asynchronous single-threaded yang elegan — kalian menulis kode yang terlihat sinkron, tapi berjalan tanpa memblokir.
Episode 7 membedah tiga pilar asynchronous programming di Dart: Future, Stream, dan Isolate. Kalian akan belajar menulis dan menggabungkan async dengan async dan await, menangani error, mentransformasi aliran data, dan memindahkan pekerjaan berat ke isolate.
Setelah episode ini, kalian akan percaya diri menulis server, client jaringan, dan aplikasi yang responsif.
Future merepresentasikan komputasi yang hasilnya tersedia belakangan:
Future<String> ambilData() async {
await Future.delayed(Duration(seconds: 1));
return 'data dari jaringan';
}
void main() async {
var data = await ambilData();
print(data);
}await ambilData() menunda eksekusi fungsi main tanpa memblokir isolate. Sementara menunggu, runtime dapat menjalankan kode lain — inilah mengapa satu thread bisa melayani banyak operasi I/O.
Async tetap perlu penanganan error. Gunakan try dan catch seperti biasa:
Future<void> cekKoneksi() async {
await Future.error(Exception('gagal koneksi'));
}
void main() async {
try {
await cekKoneksi();
} catch (e) {
print('Terjadi error: $e');
}
}await Future.error(...) melempar error yang ditangkap blok catch. Pola ini sama dengan penanganan error sinkron, sehingga transisi berpikirnya mulus.
Berbeda dari Future yang menghasilkan satu nilai, Stream menghasilkan banyak nilai seiring waktu:
import 'dart:async';
void main() {
var controller = StreamController<int>();
controller.stream.listen((data) {
print('Terima: $data');
});
controller.add(1);
controller.add(2);
controller.close();
}controller.stream.listen(...) mendaftarkan listener yang dipanggil setiap kali ada nilai baru. Pola ini dipakai untuk event, progress bar, dan pembaruan real-time.
Stream bisa ditransformasi dengan method seperti map, where, dan take:
import 'dart:async';
void main() async {
var stream = Stream.fromIterable([1, 2, 3, 4, 5]);
var genap = stream.where((n) => n.isEven).map((n) => n * 10);
await for (var nilai in genap) {
print(nilai);
}
}await for (var nilai in genap) mengonsumsi nilai stream secara berurutan. Kombinasi where dan map membentuk pipeline transformasi data yang deklaratif.
Untuk pekerjaan CPU berat seperti parsing besar atau kriptografi, jangan memblokir isolate utama. Pindahkan ke isolate lain — unit eksekusi independen yang berbagi pesan, bukan memori:
import 'dart:isolate';
void hitung(int data) {
var total = 0;
for (var i = 1; i <= data; i++) {
total += i;
}
print('Hasil: $total');
}
void main() async {
await Isolate.spawn(hitung, 1000000);
print('Isolate utama tetap responsif');
}Isolate.spawn(hitung, 1000000) menjalankan fungsi hitung di isolate baru. Karena isolate tidak berbagi memori, tidak ada race condition — komunikasi hanya lewat port dan pesan.
Asynchronous I/O menjadi tulang punggung aplikasi server dan client. Contohnya membaca file tanpa memblokir:
import 'dart:io';
Future<void> main() async {
var file = File('catatan.txt');
var isi = await file.readAsString();
print(isi);
}file.readAsString() mengembalikan Future yang diselesaikan saat seluruh isi terbaca. Untuk file besar, pakai file.openRead() yang mengembalikan Stream per-chunk. Pola yang sama berlaku untuk HTTP, database, dan socket.
Tip
Kalau kalian sering menulis await di dalam loop berurutan, pertimbangkan Future.wait untuk menjalankan tugas-tugas independen secara paralel dan menghemat waktu.
Inti yang harus dibawa pulang:
Future mewakili satu nilai di masa depan; async dan await membuatnya mudah dibaca.try dan catch seperti kode sinkron.Stream menghasilkan banyak nilai seiring waktu; listen untuk mengonsumsi, where dan map untuk transformasi.await for mengonsumsi nilai stream secara berurutan.Isolate mengeksekusi pekerjaan berat tanpa berbagi memori dengan isolate utama.readAsString, HTTP, dan database semuanya mengikuti pola async yang sama.Di episode 8 selanjutnya kita akan membahas package dan dependency management — menulis package Dart, menyusun pubspec.yaml, perbedaan package publik dan lokal, ekosistem pub.dev beserta versioning, serta penggunaan dart pub get dan dart pub upgrade.