Menu
Coddy logo textTech

Asincronía en métodos de clase

Parte de la sección Programación Orientada a Objetos del Journey de Dart de Coddy — lección 80 de 110.

Ahora que sabes cómo manejar la inicialización asíncrona con métodos de fábrica, veamos cómo hacer que los métodos de instancia regulares sean asíncronos. Esto es sencillo: simplemente añade async a cualquier método y haz que devuelva un 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');
}

Los métodos asíncronos pueden acceder y modificar variables de instancia al igual que los métodos regulares. La diferencia clave es que quienes los llaman deben usar await para el resultado. Los métodos que devuelven Future<void> no devuelven un valor, pero aun así deben ser esperados si quieres asegurarte de que se completen antes de continuar.

También puedes combinar múltiples llamadas asíncronas dentro de un método, o llamar a otros métodos asíncronos de la misma clase:

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

Este patrón es esencial para clases que interactúan con recursos externos: APIs, bases de datos o cualquier operación que tome tiempo.

challenge icon

Desafío

Fácil

¡Vamos a construir un rastreador de cartera de acciones que gestione los precios de las acciones y calcule los valores de la cartera utilizando métodos asíncronos! Crearás una clase que simule la obtención de datos de acciones en tiempo real y combine múltiples operaciones asíncronas para generar informes.

Organizarás tu código en dos archivos:

  • portfolio.dart: Crea una clase StockPortfolio que rastree las acciones y sus cantidades. Tu clase debe tener:
    • Un Map<String, int> privado llamado _holdings que almacene los símbolos de las acciones y el número de acciones en propiedad
    • Un constructor que inicialice _holdings como un mapa vacío
    • Un método addStock(String symbol, int quantity) que añada o actualice una tenencia de acciones (no asíncrono)
    • Un método asíncrono fetchPrice(String symbol) que devuelva un Future<double>. Simula un retraso de 50 milisegundos, luego devuelve un precio calculado como: la longitud del símbolo multiplicada por 25.5
    • Un método asíncrono getStockValue(String symbol) que devuelva un Future<double>. Este debe esperar a fetchPrice para el símbolo, multiplicarlo por la cantidad poseída y devolver el valor total. Si el símbolo no está en las tenencias, devuelve 0.0
    • Un método asíncrono getTotalValue() que devuelva un Future<double>. Este debe calcular el valor combinado de todas las tenencias esperando a getStockValue para cada acción y sumando los resultados
    • Un método asíncrono generateReport() que devuelva un Future<String>. Este debe construir un informe que muestre el valor de cada acción y el total. Formatea cada línea como [symbol]: $[value] (valor con 1 decimal), seguido de una línea final Total: $[totalValue] (también con 1 decimal)
  • main.dart: Importa tu archivo de cartera y demuestra cómo los métodos asíncronos funcionan juntos dentro de una clase:
    • Crea una instancia de StockPortfolio
    • Añade estas tenencias: AAPL con 10 acciones, GOOGL con 5 acciones, MSFT con 8 acciones
    • Imprime Fetching portfolio data...
    • Espera e imprime el resultado de generateReport()

¡Observa cómo generateReport() llama a otros métodos asíncronos dentro de la misma clase, y cómo cada método se basa en los demás. ¡Usa toStringAsFixed(1) para formatear los valores decimales!

Salida esperada:

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

Hoja de referencia

Para hacer que los métodos de instancia sean asíncronos, agregue la palabra clave async y devuelva un 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');
  }
}

Los métodos asíncronos pueden acceder y modificar variables de instancia. Quienes los llaman deben usar await para obtener el resultado. Los métodos que devuelven Future<void> no devuelven un valor, pero aun así deben ser esperados con await para asegurar su finalización.

Los métodos asíncronos pueden llamar a otros métodos asíncronos dentro de la misma clase:

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

Este patrón es esencial para las clases que interactúan con recursos externos como APIs o bases de datos.

Pruébalo tú mismo

import 'portfolio.dart';

void main() async {
  // TODO: Crear una instancia de StockPortfolio

  // TODO: Añadir participaciones:
  // - AAPL con 10 acciones
  // - GOOGL con 5 acciones
  // - MSFT con 8 acciones

  // TODO: Imprimir "Fetching portfolio data..."

  // TODO: Esperar (await) e imprimir el resultado de generateReport()
}
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación Orientada a Objetos