- Lập trình bất đồng bộ là gì?
Lập trình bất đồng bộ (Asynchronous Programming) là cách tổ chức chương trình cho phép một tác vụ mất thời gian được thực hiện mà không cần chặn toàn bộ chương trình trong thời gian chờ.
Trong ứng dụng thực tế, có nhiều công việc cần thời gian để hoàn thành như:
- Gọi dữ liệu từ API hoặc Internet.
- Đọc và ghi dữ liệu vào Database.
- Đọc dữ liệu từ File.
- Gửi dữ liệu lên Server.
- Thực hiện các tác vụ có thời gian chờ.
Nếu chương trình phải chờ từng tác vụ hoàn thành mới tiếp tục, ứng dụng có thể trở nên chậm hoặc không phản hồi.
Vì vậy, Dart cung cấp cơ chế lập trình bất đồng bộ thông qua các khái niệm như Future, async và await.
- Synchronous và Asynchronous
Synchronous
Synchronous là xử lý đồng bộ, các công việc được thực hiện theo thứ tự. Chương trình phải chờ công việc hiện tại hoàn thành trước khi chuyển sang công việc tiếp theo.
Có thể hiểu:
Công việc A → hoàn thành → Công việc B → hoàn thành → Công việc C
Nếu A mất nhiều thời gian thì B phải chờ A.
Asynchronous
Asynchronous là xử lý bất đồng bộ, cho phép chương trình tiếp tục thực hiện những công việc khác trong khi một tác vụ mất thời gian đang được xử lý.
Có thể hiểu:
Bắt đầu A → A đang xử lý → chương trình có thể tiếp tục công việc khác → A hoàn thành → xử lý kết quả của A
Trong Flutter, lập trình bất đồng bộ rất quan trọng vì ứng dụng thường xuyên phải làm việc với API, Database, File và các dịch vụ bên ngoài.
- Future là gì?
Future là một đối tượng trong Dart dùng để đại diện cho một kết quả sẽ có trong tương lai.
Khi một hàm thực hiện một công việc bất đồng bộ, nó thường không trả về kết quả ngay lập tức mà trả về một Future.
Ví dụ:
Future<String> getData() async {
return "Dữ liệu";
}
Future<String> có nghĩa là hàm sẽ cung cấp một giá trị String sau khi tác vụ hoàn thành.
Future thường được sử dụng cho các tác vụ như gọi API, đọc Database, đọc File hoặc các công việc có thời gian chờ.
- Trạng thái của Future
Một Future có thể được hiểu thông qua hai trạng thái chính:
Uncompleted
- Future chưa hoàn thành.
- Tác vụ bất đồng bộ vẫn đang được thực hiện và kết quả chưa có.
- Ví dụ khi ứng dụng đang gọi API thì Future có thể đang ở trạng thái chưa hoàn thành.
Completed
- Future đã hoàn thành.
- Khi hoàn thành, Future có thể: Trả về kết quả thành công, hoặc hoàn thành với một lỗi.
Có thể hiểu luồng chuyển đổi như sau:
Future → Uncompleted → Completed
Sau khi hoàn thành:
Completed → Value
hoặc:
Completed → Error
- Future<T>
Future<T> sử dụng kiểu T để xác định kiểu dữ liệu mà Future sẽ trả về.
Một số dạng thường gặp:
Future<String>
Future<int>
Future<double>
Future<User>
Future<List<Product>>
Ví dụ Future<String> có nghĩa là sau khi hoàn thành, Future sẽ cung cấp một giá trị kiểu String.
Nếu một tác vụ không cần trả về dữ liệu thì có thể sử dụng:
Future<void>
Future<void> thường được sử dụng cho những tác vụ như lưu, cập nhật hoặc xóa dữ liệu mà không cần trả về một giá trị cụ thể.
- async là gì?
async là từ khóa dùng để đánh dấu một hàm là hàm bất đồng bộ.
Khi một hàm được đánh dấu async, hàm đó thường trả về một Future.
Ví dụ:
Future<String> getName() async {
return "Thương";
}
async cho phép sử dụng await bên trong hàm để chờ các tác vụ bất đồng bộ hoàn thành.
Có thể hiểu: async → khai báo hàm bất đồng bộ.
- await là gì?
await được sử dụng để chờ một Future hoàn thành và lấy kết quả của Future đó.
Ví dụ:
final data = await getData();
Ở đây chương trình sẽ chờ getData() hoàn thành trước khi tiếp tục xử lý dòng code tiếp theo trong hàm bất đồng bộ.
await thường được sử dụng bên trong hàm có async.
Có thể hiểu:
Future→ đại diện cho kết quả trong tương laiawait→ chờ Future hoàn thành để lấy kết quả
- Mối quan hệ giữa Future, async và await
Ba khái niệm này thường đi cùng nhau:
Future→ đại diện cho kết quả sẽ có trong tương lai.async→ đánh dấu một hàm có xử lý bất đồng bộ.await→ chờ một Future hoàn thành và lấy kết quả.
Một luồng xử lý đơn giản có thể hiểu là:
Gọi hàm async → nhận Future → await chờ Future → nhận kết quả → tiếp tục xử lý
Đây là cách viết bất đồng bộ phổ biến trong Dart và Flutter.
- async/await giúp code dễ đọc hơn
Trước khi có async/await, việc xử lý nhiều tác vụ bất đồng bộ có thể sử dụng các phương thức như .then() và callback.
Khi có nhiều tác vụ liên tiếp, cách viết này có thể khiến code trở nên khó đọc.
async/await cho phép lập trình viên viết luồng xử lý gần giống với cách chương trình xử lý tuần tự:
Gọi API → chờ kết quả → xử lý dữ liệu → lưu dữ liệu → tiếp tục
Nhờ đó, code bất đồng bộ dễ đọc, dễ hiểu và dễ bảo trì hơn.
- Xử lý lỗi với async/await
Các tác vụ bất đồng bộ không phải lúc nào cũng thành công. Ví dụ như mất kết nối Internet, Server không phản hồi, API trả về lỗi, Database xảy ra lỗi, hoặc dữ liệu trả về không hợp lệ.
Khi sử dụng async/await, có thể xử lý lỗi bằng try-catch:
try {
final data = await getData();
} catch (e) {
// xử lý lỗi
}
Nếu Future hoàn thành thành công, chương trình tiếp tục xử lý kết quả.
Nếu Future xảy ra lỗi, chương trình có thể chuyển sang catch để xử lý.
Việc xử lý lỗi rất quan trọng trong ứng dụng thực tế vì không thể giả định rằng mọi tác vụ bất đồng bộ đều thành công.
- Future trong Flutter
Future xuất hiện rất thường xuyên trong các ứng dụng Flutter. Một quy trình phổ biến khi lấy dữ liệu từ API là:
Flutter → gọi API → chờ Future → nhận Response → xử lý JSON → chuyển thành Model → cập nhật State → hiển thị giao diện
Ví dụ một Service có thể có dạng:
Future<List<Product>> getProducts() async {
// gọi API
}
Điều này cho biết getProducts() sẽ trả về một List<Product> trong tương lai.
Vì vậy, hiểu Future và async/await là kiến thức nền tảng trước khi học các phần như HTTP, REST API, Dio và State Management.
- FutureBuilder trong Flutter
Flutter cung cấp FutureBuilder để xây dựng giao diện dựa trên trạng thái của một Future.
FutureBuilder thường được sử dụng để xử lý các trạng thái: Đang chờ → Có dữ liệu → Có lỗi.
Ví dụ khi gọi API lấy danh sách sản phẩm:
- Loading → API hoàn thành → hiển thị danh sách
- Nếu API xảy ra lỗi: Loading → API lỗi → hiển thị thông báo lỗi
FutureBuilder giúp kết nối quá trình xử lý Future với giao diện Flutter.
- Future và nhiều tác vụ bất đồng bộ
Trong một ứng dụng, có thể có nhiều Future cùng lúc.
Nếu các tác vụ không phụ thuộc vào nhau, có thể thực hiện chúng cùng thời điểm thay vì chờ từng tác vụ hoàn thành.
Dart cung cấp Future.wait() để chờ nhiều Future hoàn thành.
Có thể hiểu:
Future A + Future B + Future C → Future.wait() → tất cả hoàn thành → tiếp tục xử lý
Điều này có thể giúp giảm thời gian chờ khi các tác vụ hoàn toàn độc lập với nhau.
- Future không phải là Thread
Một điểm cần phân biệt là Future không phải Thread.
Future đại diện cho kết quả của một tác vụ sẽ hoàn thành trong tương lai. Trong khi đó, Thread là một cơ chế thực thi.
Dart sử dụng mô hình riêng dựa trên Event Loop, Future và Isolate để xử lý các công việc bất đồng bộ.
Vì vậy không nên hiểu đơn giản rằng: Future = một Thread chạy riêng.
Future chủ yếu dùng để quản lý và biểu diễn kết quả của các tác vụ bất đồng bộ.
- Future và Isolate
Future phù hợp với những công việc có thời gian chờ như: Gọi API, đọc Database, đọc File, Network I/O.
Tuy nhiên, nếu phải thực hiện một phép tính rất nặng, việc sử dụng Future không tự động khiến phép tính đó chạy trên một luồng xử lý riêng.
Dart cung cấp Isolate cho những trường hợp cần thực hiện các tác vụ tính toán nặng mà không muốn ảnh hưởng đến luồng xử lý giao diện.
Vì vậy:
Future & Async/Await→ tập trung vào xử lý tác vụ bất đồng bộ.Isolate & Concurrency→ tập trung nhiều hơn vào việc thực hiện công việc độc lập và xử lý các tác vụ tính toán nặng.
- Những điểm cần nhớ
Khi học Future & Async/Await, cần nhớ những ý chính sau:
Synchronous → thực hiện tuần tự và phải chờ công việc hiện tại hoàn thành.
Asynchronous → cho phép chương trình tiếp tục xử lý trong khi tác vụ khác đang chờ.
Future → đại diện cho một kết quả sẽ có trong tương lai.
Future<T> → cho biết kiểu dữ liệu mà Future sẽ trả về.
async → đánh dấu một hàm là bất đồng bộ.
await → chờ Future hoàn thành và lấy kết quả.
try-catch → dùng để xử lý lỗi trong quá trình thực hiện Future.
Future.wait() → dùng để chờ nhiều Future hoàn thành.
FutureBuilder → dùng Future để xây dựng và cập nhật giao diện Flutter theo trạng thái dữ liệu.
Không phải Thread → Future là cơ chế biểu diễn và xử lý kết quả bất đồng bộ, không phải một luồng thực thi riêng.
- Kết luận
Future và Async/Await là kiến thức nền tảng của Dart và được sử dụng rất nhiều trong Flutter.
Future đại diện cho một kết quả chưa có ngay tại thời điểm hiện tại. async được sử dụng để khai báo hàm bất đồng bộ, còn await dùng để chờ Future hoàn thành và lấy kết quả.
Trong quá trình làm Flutter, các kiến thức này đặc biệt quan trọng khi làm việc với API, Database, File, Firebase và các tác vụ có thời gian chờ.
Điều quan trọng nhất cần nhớ là:
Future = kết quả trong tương lai → async = hàm bất đồng bộ → await = chờ Future → nhận kết quả → xử lý dữ liệu hoặc lỗi





Khoá học lập trình game con rắn cho trẻ em




