Menu
CoddyTech

Bất đồng bộ trong phương thức lớp

Thuộc phần Lập trình hướng đối tượng trong hành trình Dart của Coddy. Bài học 80 trên 110.

Bây giờ bạn đã biết cách xử lý việc khởi tạo bất đồng bộ bằng các phương thức khởi tạo, hãy cùng tìm hiểu cách biến các phương thức thông thường của đối tượng thành bất đồng bộ. Việc này khá đơn giản, chỉ cần thêm async vào bất kỳ phương thức nào và để phương thức đó trả về một Future.

class WeatherService {
  String _location;
  
  WeatherService(this._location);
  
  Future<String> fetchTemperature() async {
    await Future.delayed(Duration(seconds: 1));
    return '22°C in $_location';
  }
  
  Future<void> updateLocation(String newLocation) async {
    await Future.delayed(Duration(milliseconds: 500));
    _location = newLocation;
    print('Location updated to $_location');
  }
}

Future<void> main() async {
  var service = WeatherService('London');
  var temp = await service.fetchTemperature();
  print(temp);
  
  await service.updateLocation('Paris');
}

Các phương thức bất đồng bộ có thể truy cập và chỉnh sửa biến của instance giống như phương thức thông thường. Điểm khác biệt chính là bên gọi phải dùng await để chờ kết quả. Các phương thức trả về Future<void> không trả về giá trị, nhưng bạn vẫn cần chờ chúng nếu muốn đảm bảo chúng hoàn tất trước khi tiếp tục.

Bạn cũng có thể kết hợp nhiều lời gọi bất đồng bộ trong một phương thức hoặc gọi các phương thức bất đồng bộ khác từ cùng một lớp:

Future<String> getFullReport() async {
  var temp = await fetchTemperature();
  var humidity = await fetchHumidity();
  return '$temp, Humidity: $humidity';
}

Mẫu này rất cần thiết cho các lớp (class) tương tác với tài nguyên bên ngoài, chẳng hạn như API, cơ sở dữ liệu hoặc các thao tác mất thời gian.

challenge icon

Thử thách

Dễ

Hãy xây dựng một trình theo dõi danh mục cổ phiếu để quản lý giá cổ phiếu và tính giá trị danh mục bằng các phương thức bất đồng bộ! Bạn sẽ tạo một lớp mô phỏng việc lấy dữ liệu cổ phiếu theo thời gian thực và kết hợp nhiều thao tác bất đồng bộ để tạo báo cáo.

Bạn sẽ sắp xếp code thành hai tệp:

  • portfolio.dart: Tạo một lớp StockPortfolio để theo dõi cổ phiếu và số lượng nắm giữ. Lớp của bạn cần có:
    • Một Map<String, int> riêng tư tên là _holdings để lưu mã cổ phiếu và số cổ phiếu đang sở hữu
    • Một hàm khởi tạo khởi tạo _holdings thành một từ điển rỗng
    • Một phương thức addStock(String symbol, int quantity) để thêm hoặc cập nhật số cổ phiếu nắm giữ, không bất đồng bộ
    • Một phương thức bất đồng bộ fetchPrice(String symbol) trả về Future<double>. Mô phỏng độ trễ 50 mili giây, sau đó trả về giá được tính bằng độ dài của mã cổ phiếu nhân với 25.5
    • Một phương thức bất đồng bộ getStockValue(String symbol) trả về Future<double>. Phương thức này cần chờ fetchPrice lấy giá của mã cổ phiếu, nhân với số lượng nắm giữ rồi trả về tổng giá trị. Nếu mã cổ phiếu không có trong danh sách nắm giữ, hãy trả về 0.0
    • Một phương thức bất đồng bộ getTotalValue() trả về Future<double>. Phương thức này cần tính tổng giá trị của tất cả cổ phiếu nắm giữ bằng cách chờ getStockValue cho từng cổ phiếu rồi cộng các kết quả
    • Một phương thức bất đồng bộ generateReport() trả về Future<String>. Phương thức này cần tạo báo cáo hiển thị giá trị của từng cổ phiếu và tổng giá trị. Định dạng mỗi dòng là [symbol]: $[value] (giá trị có 1 chữ số thập phân), theo sau là dòng cuối Total: $[totalValue] (cũng có 1 chữ số thập phân)
  • main.dart: Nhập tệp danh mục cổ phiếu và minh họa cách các phương thức bất đồng bộ phối hợp với nhau trong một lớp:
    • Tạo một đối tượng StockPortfolio
    • Thêm các cổ phiếu nắm giữ sau: AAPL với 10 cổ phiếu, GOOGL với 5 cổ phiếu, MSFT với 8 cổ phiếu
    • In ra Fetching portfolio data...
    • Chờ rồi in kết quả của generateReport()

Hãy chú ý cách generateReport() gọi các phương thức bất đồng bộ khác trong cùng lớp, cũng như cách mỗi phương thức dựa trên những phương thức còn lại. Dùng toStringAsFixed(1) để định dạng giá trị thập phân!

Kết quả dự kiến:

Fetching portfolio data...
AAPL: $1020.0
GOOGL: $637.5
MSFT: $816.0
Total: $2473.5

Tự làm thử

import 'portfolio.dart';

void main() async {
  // TODO: Tạo một instance của StockPortfolio

  // TODO: Thêm các cổ phiếu đang nắm giữ:
  // - AAPL với 10 cổ phiếu
  // - GOOGL với 5 cổ phiếu
  // - MSFT với 8 cổ phiếu

  // TODO: In ra "Fetching portfolio data..."

  // TODO: Chờ và in ra kết quả của generateReport()
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch Dart online