Menu
Coddy logo textTech

Futures & async/await

Teil des Abschnitts Objektorientierte Programmierung der Dart-Journey von Coddy — Lektion 76 von 110.

In realen Anwendungen nehmen viele Operationen Zeit in Anspruch – das Abrufen von Daten von einem Server, das Lesen von Dateien oder das Warten auf Benutzereingaben. Dart bewältigt diese mit Future, was einen Wert darstellt, der irgendwann in der Zukunft verfügbar sein wird.

Ein Future ist wie ein Versprechen: „Ich werde dir das Ergebnis geben, wenn es fertig ist.“ Du kannst eines mit Future.delayed() erstellen, um eine Operation zu simulieren, die Zeit in Anspruch nimmt:

Future<String> fetchUserName() {
  return Future.delayed(
    Duration(seconds: 1),
    () => 'Alice',
  );
}

Um mit dem Ergebnis eines Future zu arbeiten, verwenden Sie async und await. Markieren Sie Ihre Funktion als async und verwenden Sie dann await, um die Ausführung zu pausieren, bis das Future abgeschlossen ist:

Future<void> main() async {
  print('Fetching user...');
  String name = await fetchUserName();
  print('Hello, $name!');
}

Future<String> fetchUserName() {
  return Future.delayed(
    Duration(seconds: 1),
    () => 'Alice',
  );
}

Ohne await würden Sie ein Future<String> anstelle des tatsächlichen Strings erhalten. Das await-Schlüsselwort entpackt das Future und gibt Ihnen den darin enthaltenen Wert. Beachten Sie, dass jede Funktion, die await verwendet, als async markiert sein muss und automatisch ein Future zurückgibt.

Du kannst Werte auch direkt aus async-Funktionen zurückgeben – Dart verpackt sie automatisch in ein Future:

Future<int> calculateTotal() async {
  var a = await fetchNumber();
  var b = await fetchNumber();
  return a + b;  // Automatisch in Future<int> verpackt
}
challenge icon

Aufgabe

Einfach

Lass uns einen Wetterdienst bauen, der das Abrufen von Wetterdaten aus verschiedenen Städten simuliert! Du wirst üben, Future, async und await zu verwenden, um Operationen zu handhaben, die Zeit in Anspruch nehmen.

Du wirst deinen Code in zwei Dateien organisieren:

  • weather_service.dart: Erstelle eine WeatherService-Klasse, die das Abrufen von Wetterinformationen simuliert. Deine Klasse sollte Folgendes haben:
    • Eine Methode fetchTemperature(String city), die ein Future<int> zurückgibt. Verwende Future.delayed() mit einer Dauer von 100 Millisekunden, um eine Netzwerkverzögerung zu simulieren. Die Methode sollte eine Temperatur basierend auf dem Stadtnamen zurückgeben: Gib die Länge des Stadtnamens multipliziert mit 3 zurück.
    • Eine Methode fetchCondition(String city), die ein Future<String> zurückgibt. Verwende Future.delayed() mit 100 Millisekunden Verzögerung. Gib 'Sunny' zurück, wenn der Stadtname eine gerade Anzahl von Zeichen hat, andernfalls gib 'Cloudy' zurück.
    • Eine asynchrone Methode getFullReport(String city), die ein Future<String> zurückgibt. Diese Methode sollte sowohl auf fetchTemperature als auch auf fetchCondition warten (await) und dann einen formatierten String zurückgeben: '[city]: [temperature]C, [condition]'
  • main.dart: Importiere deinen Wetterdienst und demonstriere, wie asynchrone Operationen funktionieren. Deine main-Funktion sollte asynchron sein und:
    • Erstelle eine WeatherService-Instanz
    • Gib Fetching weather data... aus
    • Warte auf den vollständigen Bericht für 'Paris' und gib ihn aus
    • Warte auf den vollständigen Bericht für 'Tokyo' und gib ihn aus
    • Warte auf den vollständigen Bericht für 'London' und gib ihn aus
    • Gib Done! aus

Beachte, wie jeder Aufruf von getFullReport darauf wartet, dass sowohl die Temperatur als auch der Zustand abgerufen werden, bevor das kombinierte Ergebnis zurückgegeben wird. Das Schlüsselwort await pausiert die Ausführung, bis jedes Future abgeschlossen ist!

Erwartete Ausgabe:

Fetching weather data...
Paris: 15C, Cloudy
Tokyo: 15C, Cloudy
London: 18C, Sunny
Done!

Spickzettel

Ein Future repräsentiert einen Wert, der in der Zukunft verfügbar sein wird. Es wird für Operationen verwendet, die Zeit in Anspruch nehmen, wie das Abrufen von Daten oder das Lesen von Dateien.

Erstellen Sie ein Future mit Future.delayed():

Future<String> fetchUserName() {
  return Future.delayed(
    Duration(seconds: 1),
    () => 'Alice',
  );
}

Verwenden Sie async und await, um mit Futures zu arbeiten. Markieren Sie die Funktion als async und verwenden Sie await, um die Ausführung zu pausieren, bis das Future abgeschlossen ist:

Future<void> main() async {
  print('Fetching user...');
  String name = await fetchUserName();
  print('Hello, $name!');
}

Das Schlüsselwort await entpackt das Future und liefert Ihnen den tatsächlichen Wert. Ohne es würden Sie ein Future<String> anstelle des Strings erhalten.

Jede Funktion, die await verwendet, muss als async markiert sein und gibt automatisch ein Future zurück.

Rückgabewerte von async-Funktionen werden automatisch in ein Future verpackt:

Future<int> calculateTotal() async {
  var a = await fetchNumber();
  var b = await fetchNumber();
  return a + b;  // Automatically wrapped in Future<int>
}

Probier es selbst

import 'weather_service.dart';

Future<void> main() async {
  // TODO: Erstelle eine WeatherService-Instanz
  
  // TODO: Gib 'Fetching weather data...' aus
  
  // TODO: Erwarte und gib den vollständigen Bericht für 'Paris' aus
  
  // TODO: Erwarte und gib den vollständigen Bericht für 'Tokyo' aus
  
  // TODO: Erwarte und gib den vollständigen Bericht für 'London' aus
  
  // TODO: Gib 'Done!' aus
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung