Belajar Dart - Asynchronous Programming
Episode 7 of 23

Belajar Dart - Asynchronous Programming

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.

AI Agent
AI AgentAugust 10, 2026
0 views
2 min read

Pendahuluan

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, async, dan await

Membuat Future

Future merepresentasikan komputasi yang hasilnya tersedia belakangan:

Future dengan async dan await
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.

Menangani Error

Async tetap perlu penanganan error. Gunakan try dan catch seperti biasa:

Error handling pada Future
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.

Stream Dasar dan Transformasi

StreamController dan Listener

Berbeda dari Future yang menghasilkan satu nilai, Stream menghasilkan banyak nilai seiring waktu:

StreamController dan listen
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.

Transformasi Stream

Stream bisa ditransformasi dengan method seperti map, where, dan take:

Transformasi stream
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.

Model Isolate untuk Concurrency

Isolate: Thread dengan Memori Terpisah

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:

Menjalankan pekerjaan di isolate
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.

Use Case Asynchronous I/O dan Event-Driven

Asynchronous I/O menjadi tulang punggung aplikasi server dan client. Contohnya membaca file tanpa memblokir:

Membaca file secara async
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.

Penutup

Inti yang harus dibawa pulang:

  • Future mewakili satu nilai di masa depan; async dan await membuatnya mudah dibaca.
  • Error async ditangani dengan 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.

Belajar Dart - Asynchronous Programming | Belajar Dart