Future Dasar
Nilai yang datang nanti: konsep Future di Dart.
Janji akan nilai di masa depan
Program sering menunggu: mengambil data dari internet, membaca file, jeda 2 detik. Kalau program berhenti total menunggu, aplikasi macet (freeze). Future adalah cara Dart berkata: "nilainya belum ada, tapi AKAN ada. Kerjakan yang lain dulu, aku kabari kalau sudah siap."
Analogi: Future itu seperti nomor antrean di bank. Kamu tidak berdiri mematung di depan teller; kamu pegang nomor, duduk, main HP, dan dipanggil saat giliran tiba. Nomor antrean = Future, giliran dipanggil = nilai siap.
Kenapa Future ada?
Karena operasi I/O (network, file, database) lambat dibanding CPU, ribuan kali lebih lambat. Menunggu sambil diam membuang waktu. Future + async memungkinkan satu thread menangani banyak pekerjaan menunggu secara bergantian, tanpa thread tambahan yang berat.
Future dasar
// Fungsi yang mengembalikan Future<String>: butuh 2 detik
Future<String> ambilNama() {
return Future.delayed(Duration(seconds: 2), () => 'Budi');
}
void main() {
print('Mulai...');
ambilNama().then((nama) {
print('Nama diterima: $nama');
});
print('Tidak menunggu, langsung lanjut!');
}Output: "Mulai...", "Tidak menunggu, langsung lanjut!", (2 detik kemudian) "Nama diterima: Budi". Method .then() mendaftarkan callback yang jalan nanti saat Future selesai.
Tiga status Future:
- Uncompleted: masih menunggu (seperti nomor antrean di tangan).
- Completed with value: berhasil, nilainya tersedia.
- Completed with error: gagal, error-nya tersedia.
Contoh kedua, Future yang gagal:
Future<String> ambilData(bool gagal) {
return Future.delayed(Duration(seconds: 1), () {
if (gagal) throw Exception('Jaringan putus!');
return 'Data OK';
});
}
void main() {
ambilData(true).then((data) {
print(data);
}).catchError((e) {
print('Gagal: $e');
});
}.catchError() menangani kegagalan, seperti catch biasa tapi untuk dunia async.
Future.value dan Future.error
Untuk membuat Future yang langsung selesai (berguna di testing):
void main() {
Future.value(42).then((n) => print('Langsung: $n'));
Future.error('oops').catchError((e) => print('Error: $e'));
}Kesalahan umum
1. Mengira .then() menunggu
// SALAH: berharap berurutan
void main() {
String? hasil;
Future.delayed(Duration(seconds: 1), () => 'Budi').then((n) {
hasil = n;
});
// print(hasil!.length); // ERROR: hasil masih null di sini!
print('hasil belum siap saat baris ini jalan');
}// BENAR: pakai nilai DI DALAM then, atau pakai async/await
void main() {
Future.delayed(Duration(seconds: 1), () => 'Budi').then((n) {
print('Panjang nama: ${n.length}'); // 4, di dalam then
});
}Kode setelah .then() jalan SEBELUM Future selesai. Nilai Future hanya valid di dalam callback.
2. Lupa menangani error
Future yang gagal tanpa .catchError() menyebabkan unhandled async error yang sulit dilacak. Selalu pasangkan dengan penanganan error, atau pakai try-catch dengan async/await (modul berikutnya).
3. Callback hell: then bertingkat
// Bisa, tapi sulit dibaca
void main() {
Future.value(1).then((a) {
return Future.value(a + 1).then((b) {
return Future.value(b + 1).then((c) {
print(c); // 3
});
});
});
}Rantai then bertingkat adalah alasan async/await diciptakan: kode async yang terlihat sinkron.
Kesimpulan
Future = nilai masa depan dengan 3 status (menunggu/berhasil/gagal). .then() untuk sukses, .catchError() untuk gagal. Ingat: kode di luar callback jalan duluan. Di modul berikutnya, async/await membuat semua ini jauh lebih enak dibaca.
Catatan teknis: Future di Dart berjalan di event loop single-threaded, bukan thread terpisah. Operasi I/O didelegasikan ke sistem, dan callback dijadwalkan kembali saat selesai. Model ini ringan: ribuan Future tidak seberat ribuan thread.
Tantangan
Simulasi unduhan
Buat fungsi unduh(String file) yang mengembalikan Future<String> berisi "$file selesai" setelah 1 detik. Panggil untuk 2 file dan cetak hasilnya dengan then.
// TODO: fungsi unduh
void main() {
// TODO
}