Anfordern von Daten mit offenem Ende

  • Anfordern von Daten mit offenem Ende

    Ich plane aktuell folgenden Javascript Code clientseitig umzusetzen, dafür wollte ich mir Anregungen holen, da ich was AJAX angeht auch noch sehr neu bin.

    Folgende Schritte sollen, nachdem der User einen Button geklickt hat passieren:
    1. Button wird disabled
    2. Ein AJAX Request an ein PHP Script wird durchgeführt, dieser liefer JSON Daten, einmal eine Unique ID und außerdem 6 URLs
    3. Die 6 URLs müssen im Hintergrund aufgerufen werden
    4. Nachdem die 6 URLs jeweils 1x geöffnet wurden muss ein weiteres PHP Script aufgerufen werden (via GET und mit Übergabe der Unique ID aus Schritt 2). Dieses Script liefert JSON Daten zurück, diese stelle ich nun im HTML an bestimmten Stellen dar.
    5. Button wird wieder klickbar gemacht
    Während der Schritte 1-5 soll außerdem eine "Ladeanimation" (GIF Bild eingeblendet) werden. Kann mir jemand Tipps geben, wie ich das am besten umsetze?

    All the best;
  • Ok, ich würde mein Beispiel gerne mit der aktuellen API und ES6 schreiben. Du müsstest also ein paar Polyfills mit laden (z.B. fetch) und eventuell auf ES5 transpilieren. In meinem Beispiel hat die gif ein display="none". Etwas ausgefeilter lässt es sich aber mit zu und abschalten von css-Klassen machen.

    JavaScript-Quellcode

    1. const button = document.querySelector('#my-button') // Den Button in's JS hohlen
    2. const gif = document.querySelector('#my-gif') // Die gif in's JS hohlen
    3. button.onclick = event => { // Button-Click registrieren
    4. event.preventDefault() // Defaults abschalten
    5. button.disabled = true // Button disablen (1.)
    6. gif.style.display = 'block' // gif einblenden
    7. fetch('/my.php') // Der erste request (2.)
    8. .then(response => response.json()) // JSON aus der Antwort entnehmen
    9. .then(json => {
    10. json.urls.forEach(url => window.open(url)) // Für jede URL ein Tab / Fenster öffnen (3.)
    11. return fetch('/my2nd.php?id=' + json.id) // 2. Request (4.)
    12. })
    13. .then(response => response.json()) // JSON aus der Antwort entnehmen
    14. .then(json => {
    15. // mach dein Ding mit dem json-Object
    16. button.disabled = false // Button enablen (5.)
    17. gif.style.display = 'none' // gif ausblenden
    18. })
    19. .catch(err => console.error(err)) // Fehlerbehandlung
    20. }
    Alles anzeigen
  • Wenn du die Seiten nur in den Cache laden möchtes, würde das wohl so funktioniern:

    JavaScript-Quellcode

    1. json.urls.forEach(url => fetch(url))
    Die Seiten werden mit GET geladen, aber nichts mit deren Inhalt getan.


    Ansonsten könntest du auch die Seiten in neuen (versteckten) iframe-Elementen laden. Diese werden dann auch ausgeführt und du kannst mit ihnen interagieren und sie später natürlich sichbar machen.

    Ebenso könntest du das template-Element verwenden. Hier wird der Inhalt weder ausgeführt noch angezeigt.

    Es gibt auch noch die HTML-Imports, aber die sind noch nicht so weit.
  • Was genau ist das denn für JS was du da eben verwendest?
    jQuery ist es doch nicht?
    -Wo finde ich dazu Details?

    Eine Idee, wie ich dann meine 2. Antwort vom PHP Script parsen kann?

    Quellcode

    1. {
    2. "ips":[
    3. {
    4. "ip":"XYZ",
    5. "country":"Denmark",
    6. "city":null
    7. },
    8. {
    9. "ip":"ZYX",
    10. "country":"Denmark",
    11. "city":"Hvidovre"
    12. }
    13. ]
    14. }
    Alles anzeigen
  • Das ist natives JS in der Version ES6/ES2015 ohne Bibliotheken wie JQuery. Dazu noch die aktuelle DOM-API.

    Entschuldigung, aber die Resourcen, die ich für gewöhnlich verwende sind in Englisch:

    DOM:
    ES6:


    Das parsen des JSON wird in meinem Beispiel in der Zeile response.json() erledigt. Ansonsten wäre auch JSON.parse() möglich.
  • Lichtjaeger schrieb:

    Das parsen des JSON wird in meinem Beispiel in der Zeile response.json() erledigt. Ansonsten wäre auch JSON.parse() möglich.
    Hier ist mein Versuch nun das JSON (siehe 2 Posts zuvor) zu parsen. Wo liegt mein Fehler?

    Quellcode

    1. .then(json => {
    2. json.ips.forEach(ips => console.log(ips.ip.country));
    3. // mach dein Ding mit dem json-Object
    4. button.disabled = false // Button enablen (5.)
    5. gif.style.display = 'none' // gif ausblenden
    6. })
  • Huhey,

    ich bekomme manchmal keinerlei Daten von PHP zurück, ich denke das die Abfrage zu schnell von Javascript aus erfolgt, also PHP in diesem Fall noch zu dem Zeitpunkt der Abfrage keinerlei Daten aus der DB erhält.
    Das Problem variiert aber, es tritt manchmal auf (erhalte dann auch keine Konsolenausgabe mit der IP, daher mein Verdacht mit dem quasi "zu schnellen" Javascript).

    Meine Idee nun, bevor der Request gestartet wird, der das Ergebnis abfragt quasi einen sleep einbauen, um sicherzugehen, dass die Daten bereitliegen und PHP diese abfragen kann.

    -Wie baue ich das an der markierten Stelle (vor dem Request) am besten ein?

    Quellcode

    1. <script>
    2. const button = document.querySelector('.btn')
    3. const gif = document.querySelector('#my-gif')
    4. button.onclick = event => { // Button-Click registrieren
    5. event.preventDefault()
    6. button.disabled = true
    7. gif.style.display = 'block'
    8. fetch('/get')
    9. .then(response => response.json())
    10. .then(json => {
    11. json.urls.forEach(url => fetch('http://' + url + '.xyz.de'))
    12. //wait lets say 3 seconds?
    13. return fetch('/results?id=' + json.id)
    14. })
    15. .then(response => response.json())
    16. .then(json => {
    17. $("#result-table").find("tr:gt(0)").remove();
    18. jQuery.each(json.ips, function()
    19. {
    20. console.log(this.ip);
    21. if(this.city == null)
    22. city = '--';
    23. else
    24. city = this.city;
    25. var table = document.getElementById("result-table");
    26. var row = table.insertRow(1);
    27. var cell1 = row.insertCell(0);
    28. var cell2 = row.insertCell(1);
    29. var cell3 = row.insertCell(2);
    30. cell1.innerHTML = this.ip;
    31. cell2.innerHTML = this.country;
    32. cell3.innerHTML = city;
    33. console.log(this.ip);
    34. });
    35. button.disabled = false // Button enablen (5.)
    36. gif.style.display = 'none' // gif ausblenden
    37. })
    38. //.catch(err => console.error(err)) // Fehlerbehandlung
    39. }
    40. </script>
    Alles anzeigen
  • Du könntest die Zeilen 10 und 16 zu debug-Zwecken folgendermassen umschreiben:

    JavaScript-Quellcode

    1. .then(response => {
    2. console.log(response.statusText)
    3. return response.json()
    4. })


    Wenn es keinen Fehler gibt, sollte "OK" ausgegeben werden. Ansonsten ein Fehlertext.

    Muss dein 2. php-Script auf die 6 urls warten? Falls ja, versuch:

    JavaScript-Quellcode

    1. .then(json =>
    2. Promise.all(json.urls.map(url => fetch('http://' + url + '.xyz.de')))
    3. .then(() => fetch('/results?id=' + json.id))
    4. )

    Der Request wird dann erst ausgeführt, wenn alle urls geladen wurden.


    Für ein quasi-sleep müssen wir ein zusätzliches Promise einfügen:

    JavaScript-Quellcode

    1. .then(json => {
    2. json.urls.forEach(url => fetch('http://' + url + '.xyz.de'))
    3. return new Promise(resolve => {
    4. window.setTimeout(() => resolve(fetch('/results?id=' + json.id)), 3000)
    5. })
    6. })
    7. // Oder "Chain-Style"
    8. /*
    9. .then(json => {
    10. json.urls.forEach(url => fetch('http://' + url + '.xyz.de'))
    11. return (new Promise(resolve => {
    12. window.setTimeout(resolve, 3000)
    13. })).then(() => fetch('/results?id=' + json.id))
    14. })
    15. */
    Alles anzeigen

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Lichtjaeger ()