ข้ามไปยังเนื้อหา

Future และ Async/Await

Future<T> ใน Dart คือ Promise<T> ใน JavaScript ทั้งคู่แทนค่า single value ที่ยังไม่พร้อมใช้งาน — จะมาถึง (หรือล้มเหลว) ในบางจุดในอนาคต แนวคิดทุกอย่างที่คุณรู้จาก JS Promise แมปได้โดยตรง: .then(), .catch(), async/await, try/catch และการประมวลผลแบบ parallel ด้วย Future.wait / Promise.all mental model เหมือนกัน เพียงแต่ API surface เปลี่ยนไปเล็กน้อย

React
// --- Promise chain style ---
function loadUser(id) {
return fetch(`/api/users/${id}`)
.then(res => res.json())
.then(data => {
console.log('User:', data.name);
return data;
})
.catch(err => {
console.error('Failed:', err.message);
});
}
// --- async/await style ---
async function loadUserAsync(id) {
try {
const res = await fetch(`/api/users/${id}`);
const data = await res.json();
console.log('User:', data.name);
return data;
} catch (err) {
console.error('Failed:', err.message);
}
}
Flutter
// --- Future chain style ---
Future<void> loadUser(String id) {
return Future.delayed(
const Duration(seconds: 1),
() => {'name': 'Ava', 'id': id},
)
.then((data) {
print('User: ${data['name']}');
})
.catchError((err) {
print('Failed: $err');
});
}
// --- async/await style ---
Future<void> loadUserAsync(String id) async {
try {
// Simulating an HTTP call with Future.delayed
final data = await Future.delayed(
const Duration(seconds: 1),
() => {'name': 'Ava', 'id': id},
);
print('User: ${data['name']}');
} catch (err) {
print('Failed: $err');
}
}

แอปด้านล่างแสดงการทำงานของ FutureBuilder ที่ consume Future.delayed — รูปแบบ Flutter ที่เทียบเท่ากับ useEffect(() => { fetch(...).then(setData) }, []) สังเกต spinner หายไปและผลลัพธ์ปรากฏหลังจากสองวินาที

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
        body: Center(child: FutureDemo()),
      ),
    );
  }
}

// Simulates a network call — replace with http.get() in a real app.
Future<String> fetchMessage() {
  return Future.delayed(
    const Duration(seconds: 2),
    () => 'Hello from the future!',
  );
}

class FutureDemo extends StatefulWidget {
  const FutureDemo({super.key});

  @override
  State<FutureDemo> createState() => _FutureDemoState();
}

class _FutureDemoState extends State<FutureDemo> {
  // Hold the Future in state so it does not restart on every rebuild.
  late final Future<String> _messageFuture;

  @override
  void initState() {
    super.initState();
    _messageFuture = fetchMessage();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<String>(
      future: _messageFuture,
      builder: (context, snapshot) {
        // ConnectionState.waiting === Promise pending
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              CircularProgressIndicator(),
              SizedBox(height: 16),
              Text(
                'Awaiting the future...',
                style: TextStyle(color: Colors.grey, fontSize: 14),
              ),
            ],
          );
        }

        // snapshot.hasError === Promise rejected
        if (snapshot.hasError) {
          return Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              const Icon(Icons.error_outline, color: Colors.red, size: 40),
              const SizedBox(height: 12),
              Text(
                'Error: ${snapshot.error}',
                style: const TextStyle(color: Colors.red, fontSize: 14),
              ),
            ],
          );
        }

        // snapshot.data present === Promise resolved
        return Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            const Icon(Icons.check_circle_outline,
                color: Colors.green, size: 48),
            const SizedBox(height: 12),
            Text(
              snapshot.data ?? '',
              style: const TextStyle(
                  fontSize: 22, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 8),
            const Text(
              'Future resolved — like a Promise.then() callback.',
              style: TextStyle(color: Colors.grey, fontSize: 13),
              textAlign: TextAlign.center,
            ),
          ],
        );
      },
    );
  }
}
Future ใน Dart เทียบเท่ากับอะไรใน JavaScript?
เมธอดใดใน Future ที่เทียบเท่ากับ .catch() ใน Promise?
ถ้า Future ล้มเหลวและไม่มีการจัดการ error จะเกิดอะไรขึ้น?