Rolf B: Globale Variable

Beitrag lesen

Hallo Suspekta,

deine Frage ist weder dumm noch sehr einfach. Promises sind komplexe Biester.

Du musst beachten, dass die Funktionen getISS und getData nach dem ersten await erstmal enden und ein Promise zurückgeben, das sich erst erfüllt, wenn der Rest der Funktion durchgelaufen ist.

Im Selfhtml Wiki findest Du Basisinformationen zu Promises.

Der Rest der beiden Funktionen wird dann als sogenannter Mikrotask ausgeführt - aber eben asynchron, irgendwann später, nach dem getISS() Aufruf und auch nach der Zuweisung an data_api. Deswegen fehlt Dir da die sat_id.

Wenn Du in getData Daten aus getISS benötigst, dann musst Du das Promise, das Dir getISS als async-Funktion liefert, nutzen, um darauf zu warten. Du musst auch sat_id irgendwo deklarieren, andernfalls wird es zu einer globalen Variablen (oder wird Dir im strict mode um die Ohren gehauen).

Du solltest auch wenn möglich auf die Nutzung globaler Variablen verzichten und Daten explizit übergeben. Das macht die Funktionen flexibler und den Datenfluss besser sichtbar. Du solltest auch beim Zuweisen an HTML Elemente nur dann innerHTML verwenden, wenn Du wirklich willst, dass der HTML-Parser läuft. Für Text ist textContent zu verwenden.

const sat_url= 'https://api.wheretheiss.at/v1/satellites',
      global_id = document.getElementByID("GID");

async function getISS(url) {
   const response  = await fetch(sat_url);
   if (!response.ok) {
      // Hier fehlt Error-Handling!
   }
   const data = await response.json();
   sat_id = data[0].id;
   global_id.innerHTML=sat_id;
   console.log(global_id.innerHTML);
   return sat_id;                    // <<<- await gibt dies zurück
}

async function getData(url) {        // Edited: Parameter!
   const response = await fetch(url);
   if (!response.ok) {
      // Hier fehlt Error-Handling!
   }
   return response.json();           // <<<- await gibt dies zurück
}

const sat_id = await getISS(sat_url);
const data   = await getData(sat_url + '/' + sat_id);

document.getElementById("LAT").textContent = data.latitude;
document.getElementById("LNG").textContent = data.longitude;

Wenn Du jetzt eine Fehlermeldung bekommst, dass await auf Top-Level nicht erlaubt ist, hast Du mehrere Optionen:

  • das ganze muss in eine async-Funktion verpackt werden
  • das Script muss als ES6-Modul laufen (<script type="module">...</script>), was aber auch automatisch den strict mode aktiviert.
  • Du verzichtest auf Top-Level await und verwendest statt der letzten vier Codezeilen die then-Methode des Promise, das von den async-Funktionen zurückkommt:
getISS(sat_url)
.then(sat_id => getData(sat_url + '/' + sat_id))
.then(data => {
  document.getElementById("LAT").textContent = data.latitude;
  document.getElementById("LNG").textContent = data.longitude;
})
.catch(error => /* Errorhandling */);

await ist lediglich Syntaxzucker für dieses .then-Konstrukt. Im ersten .then() gibt die Handlerfunktion das Promise zurück, das von getData() geliefert wird. Die then-Funktion ist so schlau, das zu erkennen und erstmal auf dieses Promise zu warten, bis es mit dem zweiten .then weitergeht. Das Gleiche gilt für die getData-Funktion selbst: response.json() liefert ein Promise, nicht das fertige Objekt, und das Promise der async-Funktion koppelt sich automatisch daran. Promises sind wie Kaninchen: sie vermehren sich hemmungslos.

Der wichtigste Unterschied zwischen then und await ist: Wenn ein Promise rejected wird (was im Fetch bei Datenfehlern oder bei einem 500er-Statuscode im HTTP Request passieren kann), wirft await einen Error, den Du mit try/catch fangen musst. Wenn Du mit .then arbeitest, wird kein Error geworfen, aber du musst für das zurückgewiesene Promise mit einem .catch()-Aufruf einen Handler registrieren.

Rolf

--
sumpsi - posui - obstruxi