Menu
CoddyTech

Асинхронность в методах классов

Часть раздела Объектно-ориентированное программирование путешествия по Dart на Coddy. Урок 80 из 110.

Теперь, когда ты знаешь, как обрабатывать асинхронную инициализацию с помощью фабричных методов, давай посмотрим, как сделать обычные методы экземпляра асинхронными. Это просто: добавь async к любому методу и сделай так, чтобы он возвращал 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');
}

Асинхронные методы могут получать доступ к переменным экземпляра и изменять их так же, как обычные методы. Главное отличие заключается в том, что вызывающий код должен использовать await для получения результата. Методы, возвращающие Future<void>, не возвращают значение, но их всё равно нужно ожидать, если вы хотите убедиться, что они завершатся до продолжения выполнения.

Вы также можете объединять несколько асинхронных вызовов в одном методе или вызывать другие асинхронные методы того же класса:

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

Этот шаблон необходим для классов, взаимодействующих с внешними ресурсами — API, базами данных или любыми операциями, требующими времени.

challenge icon

Задание

Легко

Давай создадим трекер инвестиционного портфеля, который управляет ценами акций и рассчитывает стоимость портфеля с помощью асинхронных методов! Ты создашь класс, имитирующий получение данных об акциях в реальном времени и объединяющий несколько асинхронных операций для создания отчётов.

Ты организуешь код в два файла:

  • portfolio.dart: создай класс StockPortfolio, который отслеживает акции и их количество. В твоём классе должны быть:
    • Приватная Map<String, int> с именем _holdings, в которой хранятся биржевые символы и количество принадлежащих владельцу акций
    • Конструктор, который инициализирует _holdings как пустую карту
    • Метод addStock(String symbol, int quantity), который добавляет или обновляет запись об акции (не асинхронный)
    • Асинхронный метод fetchPrice(String symbol), который возвращает Future<double>. Имитируй задержку в 50 миллисекунд, а затем возвращай цену, рассчитанную так: длина биржевого символа, умноженная на 25.5
    • Асинхронный метод getStockValue(String symbol), который возвращает Future<double>. Он должен дождаться результата fetchPrice для этого биржевого символа, умножить его на количество акций во владении и вернуть общую стоимость. Если биржевого символа нет в портфеле, верни 0.0
    • Асинхронный метод getTotalValue(), который возвращает Future<double>. Он должен рассчитать общую стоимость всех активов, дождавшись результата getStockValue для каждой акции и сложив полученные значения
    • Асинхронный метод generateReport(), который возвращает Future<String>. Он должен составить отчёт со стоимостью каждой акции и общей стоимостью. Отформатируй каждую строку как [symbol]: $[value] (значение с 1 десятичным знаком), а в последней строке укажи Total: $[totalValue] (также с 1 десятичным знаком)
  • main.dart: импортируй файл портфеля и покажи, как асинхронные методы взаимодействуют внутри класса:
    • Создай экземпляр StockPortfolio
    • Добавь следующие активы: AAPL — 10 акций, GOOGL — 5 акций, MSFT — 8 акций
    • Выведи Fetching portfolio data...
    • Дождись результата generateReport() и выведи его

Обрати внимание, что generateReport() вызывает другие асинхронные методы того же класса и что каждый метод опирается на результаты предыдущих. Используй toStringAsFixed(1), чтобы форматировать десятичные значения!

Ожидаемый результат:

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

Попробуйте сами

import 'portfolio.dart';

void main() async {
  // TODO: Создайте экземпляр StockPortfolio

  // TODO: Добавьте позиции:
  // - AAPL с 10 акциями
  // - GOOGL с 5 акциями
  // - MSFT с 8 акциями

  // TODO: Выведите "Fetching portfolio data..."

  // TODO: Дождитесь результата generateReport() и выведите его
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Онлайн-компилятор Dart