Javascript: wie im Script auf async warten

X__

Lieutenant
Registriert
Okt. 2002
Beiträge
647
Hallo,

ich bin dabei für meine Heimautomatisation (openHAB) eine kleine HTML-Erweiterung
zu bauen. Darin soll möglichst einfach eine dynamische Tabelle (Ladestandsanzeigen von Batterien)
erzeugt werde.

Dazu habe ich ein HTML-Grundgerüst erschaffen. In dieses Grundgerüst möchte ich ein Javascript einbauen, dass mir
die Tabelle je nach den gelieferten Daten erweitert.

Das Javascript soll möglichst einfach gehalten werden und nur dafür sorgen, dass ein bereits fertiger String in das HTML-Gerüst
eingespleisst wird (Zeile 18). Das gesamte Aufbereiten der Daten und bereitstellen als String übernimmt serverseitig ein JRuby Programm und auf den aufbereiteten String greife ich über eine REST Api zu.

Vom Prinzip funktioniert das (siehe erstes Ergebnis) nur der async-Aufruf scheint mir dazwischen zu hauen (siehe zweites Ergebnis).
Wie kann ich das Problem beheben ?

PS: Nicht wundern: Zum Testen ist im HTML bereits "Batterie 1" mit enthalten - das fliegt natürlich später raus.

HTML:
<!DOCTYPE html>
<html lang="de">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Titel der Seite | Name der Website</title>
    <link rel="stylesheet" href="css/glob_battchecker.css">  
  </head>
  <body>
    Batterie-Ladezustände
    <table>
        <tr>
            <th>Gerät</th><th>Zustand</th>
        </tr>
        <tr>
            <td>Batterie 1</td><td>10%</td>
        </tr>
        <script language="JavaScript" src="js/glob_battchecker.js" async></script>                      
    </table>  
  </body>
</html>

Das funktioniert:
Ein fixer String, wie ihn der GET Aufruf zurückbringen würde.
Dazu muss aus dem Script-Aufruf im HTML allerdings das "async" entfernt werden
Javascript:
'use strict';
let tabledata = '<tr><td>Batterie 2</td><td>14 %</td></tr><tr><td>Batterie 3</td><td>22 %</td></tr>';
document.write(tabledata);

Ergebnis 1:
1705956929669.png


Das funktioniert nicht:
Der GET Aufruf bekommt zwar die richtigen Daten (identisch, wie der fixe String aus dem ersten Beispiel),
diese werden aber erst viel zu spät bereitgestellt, wodurch die ganze HTML-Seite anscheinend wieder überschrieben wird.
Javascript:
'use strict';
async function fetchData() {
    const theUrl = 'http://192.168.0.20:8088/gimmesometabledata';

    const response = await fetch(theUrl)
    .then(res => { 
        if (res.ok) { 
            console.log("HTTP request successful")
        }
        else {
             console.log("HTTP request unsuccessful") 
            }
        return res
    })
    const data = await response.text();
    return data;
}
fetchData().then( data => { 
    console.log("data=" + data);
    document.write(data);   
});

Ergebnis 2:
1705957867929.png
 
Hi, du könntest versuchen, den Table mit entsprechenden Bereichen (thead, tbody) zu ergänzen:
Code:
    <table>
        <thead>
        <tr>
            <th>Gerät</th><th>Zustand</th>
        </tr>
        </thead>
        <tbody id="content">
        <tr>
            <td>Batterie 1</td><td>10%</td>
        </tr>
        </tbody>
        <script language="JavaScript" src="js/glob_battchecker.js" async></script>                     
    </table>

Und dann statt document.write(data) sowas zu verwenden:
Code:
document.querySelector('#content').innerHTML = data;
 
  • Gefällt mir
Reaktionen: floTTes und FranzvonAssisi
Was QXARE geschrieben hat sollte funktionieren.

Nur als Erklärung noch:
Das Problem ist nicht, dass es zu lange dauert, sondern, dass document.write das ganze document überschreibt und nicht nur einen kleinen Teil. :)

Lg
 
Danke. für den Tipp.
Ich werds heute abend mal ausprobieren und dann berichten.

FranzvonAssisi schrieb:
dass document.write das ganze document überschreibt

Aber warum klappt dass denn in der ersten Version, in der lediglich kein asynchroner Aufruf stattfindet ?
 
Because document.write() writes to the document stream, calling document.write() on a closed (loaded) document automatically calls document.open(), which will clear the document.

Ist viel ungefährlicher die Daten in generierte Elemente zu geben.

HTML:
<body>
    <h1>Meine Batterien</h1>
    <table>
        <thead>
            <tr>
                <th>Gerät</th>
                <th>Zustand</th>
            </tr>
        </thead>
        <tbody id="tbBatCond">
            <tr>
                <td>Batterie A</td>
                <td>10%</td>
            </tr>
        </tbody>
        <tfoot>
        </tfoot>
    </table>
</body>
<script>
    function addBatCondToTable(bid, bcond, tbid = "tbBatCond") {
        const row = document.getElementById(tbid).insertRow(-1);
        const cellcont = {
            id: row.insertCell(-1).innerHTML = bid,
            cond: row.insertCell(-1).innerHTML = bcond
        };

        return row;
    }

    addBatCondToTable("Batterie B", "25%");
</script>
 
Zuletzt bearbeitet:
Danke für die Tipps - funktioniert super :)
 
Zurück
Oben