Async dan Future
Menangani operasi lambat tanpa macet: Future, async, await, dan then.
Kenapa butuh async?
Mengambil data dari internet butuh waktu. Kalau program menunggu (blocking), seluruh aplikasi macet: tombol tidak bisa diklik, animasi berhenti. Solusinya: operasi asynchronous, program lanjut jalan sambil menunggu hasil.
Future<String> ambilData() {
// simulasi network request 2 detik
return Future.delayed(Duration(seconds: 2), () => 'Data tiba!');
}
void main() async {
print('Mulai...');
String hasil = await ambilData(); // tunggu di sini, tapi tidak macet
print(hasil);
print('Selesai');
}Output: Mulai..., (tunggu 2 detik), Data tiba!, Selesai.
Future<String>= "janji" nilai String yang datang nantiasyncpada main = fungsi ini boleh pakaiawaitawait= tunggu Future selesai, lalu lanjutkan dengan hasilnya
Future: janji yang bisa gagal
Future punya tiga status: uncompleted (menunggu), completed (sukses dengan nilai), error (gagal). Menangani error pakai try-catch seperti biasa:
Future<String> ambilUser(int id) async {
await Future.delayed(Duration(seconds: 1));
if (id <= 0) throw Exception('ID tidak valid');
return 'User $id';
}
void main() async {
try {
var user = await ambilUser(-1);
print(user);
} catch (e) {
print('Gagal: $e');
}
}Fungsi yang ditandai async otomatis mengembalikan Future, jadi ambilUser yang terlihat mengembalikan String sebenarnya mengembalikan Future<String>.
Catatan teknis: Lupa
awaitadalah bug async paling umum. Tanpaawait, kamu dapat object Future-nya, bukan nilainya. Gejalanya:print(hasil)mencetakInstance of 'Future<String>'bukannya data. Kalau melihat teks itu, 99% kamu lupaawaitatau fungsi pemanggilnya belumasync.
then: gaya tanpa await
Alternatif await adalah method then:
Future<String> ambilData() {
return Future.delayed(Duration(seconds: 1), () => 'Data tiba!');
}
void main() {
ambilData().then((hasil) {
print(hasil);
}).catchError((e) {
print('Error: $e');
});
print('Tidak menunggu');
}Output: Tidak menunggu dulu, baru Data tiba!. Gaya then berguna untuk operasi cepat satu-dua langkah, tapi untuk alur panjang async/await jauh lebih terbaca.
Menjalankan banyak Future sekaligus
Jangan await satu per satu kalau tidak saling bergantung:
Future<String> ambilA() => Future.delayed(Duration(seconds: 2), () => 'A');
Future<String> ambilB() => Future.delayed(Duration(seconds: 2), () => 'B');
void main() async {
// Lambat: total 4 detik
// var a = await ambilA();
// var b = await ambilB();
// Cepat: total 2 detik, jalan paralel
var hasil = await Future.wait([ambilA(), ambilB()]);
print(hasil); // [A, B]
}Future.wait menjalankan semua Future bersamaan dan menunggu semuanya selesai. Pola ini wajib saat mengambil beberapa data API sekaligus di aplikasi nyata.
async di dunia nyata
Di Flutter, hampir semua interaksi penting itu async: HTTP request, baca database lokal, akses kamera, baca file. Memahami Future di Dart murni membuat kode Flutter seperti ini langsung masuk akal:
Future<void> simpanDanTampilkan() async {
print('Menyimpan...');
await Future.delayed(Duration(seconds: 1)); // simulasi simpan ke DB
print('Tersimpan, menampilkan data terbaru');
await Future.delayed(Duration(milliseconds: 500)); // simulasi refresh
print('Selesai');
}
void main() async {
await simpanDanTampilkan();
}Aturan emas async
- Fungsi yang pakai
awaitwajib ditandaiasync asyncmengubah return jadi Future (kecuali return-nya void, jadiFuture<void>)- Jangan campur
awaitdanthendalam satu alur, pilih satu gaya - Error di Future ditangkap dengan try-catch di sekitar
await
Kuasai ini dan kamu siap menghadapi 80% kebutuhan aplikasi nyata: loading data, menyimpan, dan semua yang butuh "tunggu sebentar".