Suspekta: Globale Variable

Hallo,

wahrscheinlich eine dumme/sehr einfach Frage aber ich komme nicht drauf. Ich habe eine API URL von der ich Daten hole. Diese Daten brauche ich dann für eine neue API Abfrage. Irgendwie kann ich aber auf die Variablen aus der 1. Funktion nicht zugreifen. Die data_api ist hier fest hinterlegt aber die 25544 kommt aus der Funktion (sat_id).

Sollte sein wie const data_api = 'https://api.wheretheiss.at/v1/satellites/'+sat_id;

Hier habe ich es sogar noch versucht die sat_id in ein <p> zu "speichern" funkt aber ich nicht 😟

Gibt es eine Lösung?

const sat_url = 'https://api.wheretheiss.at/v1/satellites';
        const global_id = document.getElementById("GID");
     
        async function getISS() {
           const response  = await fetch(sat_url);
           const data = await response.json();
           sat_id = data[0].id;
           global_id.innerHTML=sat_id;
           console.log(global_id.innerHTML);
       }

       async function getData() {
            const response = await fetch(data_api);
            const data = await response.json();
            document.getElementById("LAT").innerHTML = data.latitude;
            document.getElementById("LNG").innerHTML = data.longitude;
        }

       getISS(); 


   const data_api='https://api.wheretheiss.at/v1/satellites/'+sat_id;

  
       getData();Quelltext hier
  1. 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
    1. Hallo Rolf,

      super herzlichen Dank für deine Ausführliche Antwort. Ich habe es auch jetzt hinbekommen. Hier hattest du noch einen "Fehler" im getData aufruf. Hier hast du die URL übergeben aber getData hatte keinen Parameter, dass habe ich geändert und es läuft 😀
      Edit Rolf B: Ich habe das Beispiel korrigiert!

      Aber du hattest auch mit der Fehlermeldung recht. Es geht nur mit ".then"

      Danke nochmal für deine Hilfe!!

      Hier nochmal der Code der läuft ...

       const sat_url= 'https://api.wheretheiss.at/v1/satellites';
        
              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;
                  return sat_id;                    // <<<- await gibt dies zurück
              }
      
              async function getData(data_url) {
                  const response = await fetch(data_url);
                  if (!response.ok) {
                      // Hier fehlt Error-Handling!
                  }
                  return response.json();           // <<<- await gibt dies zurück
              }
      
      
              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 => error);
      
      1. Hallo Suspekta,

        danke für den Hinweis auf den Fehler. Das kommt davon, wenn man Beispiele am grünen Tisch erstellt und nicht ausprobiert…

        Ich habe den Beispielcode berichtigt und in deine Antwort einen entsprechenden Vermerk hineineditiert.

        Es geht nur mit .then

        Wie geschrieben geht es auch anders, aber mit .then ist es vermutlich am einfachsten 😉

        .catch(error => error);

        Ich hoffe, das feilst Du noch aus. Natürlich kann man Fehler einfach unterdrücken, aber man sollte sie zumindest in die Konsole loggen. Vergessenes Errorhandling kann zu stundenlanger Fehlersuche führen.

        Rolf

        --
        sumpsi - posui - obstruxi
        1. Hallo Rolf,

          was die Error Geschichte angeht kenn ich mich schon aus und mache das im "echten" produktiven Leben immer, keine Sorge 😀

          Ich programmiere schon seit knapp 20 Jahren aber nicht JavaScirpt. Das wollte ich jetzt mal nachholen.

          Bislang schreibe ich Anwendungsprogramme/ERP-Systeme für Windows in VB und c#

          LG Suspekta

          nachmals vielen Dank für deine Hilfe!