piet: Javascript und XMLHttpRequest

Hallo,

ich habe in einem Array diverse IP-Adressen. Über eine Schleife lese ich von jeder IP-Adresse (Server) diverse Daten aus.

Zwei Fragen

  1. Wenn ich über httpRequest.open("get",ip_adresse[i] + "?" + var_name[i],false); synchron-Modus lese, wie kann ich einen Timeout abfangen/erzeugen, falls eine Adresse nicht funktioniert ? In vielen Google-Artikeln steht, das es im synchron-Modus keine Timeoutüberwachung gibt. Das kann ich mir aber nicht vorstellen.

  2. Wenn ich über httpRequest.open("get",ip_adresse[i] + "?" + var_name[i],true); im asynchron-Modus die Daten hole, kann ich dem callback-Programm einen Parameter mitgeben ?

Beispiel: httpRequest.onreadystatechange = updatePage(schleifenzaehler); Wäre so etwas möglich, damit ich weiß welcher callback-Aufruf zu welchem Parameter/IP-Satz gehört ?

Ich hoffe ich konnte es gut erklären 😅

Gruß piet

  1. @@piet

    1. Wenn ich […] [im] synchron-Modus lese

    Warum willst du das tun?

    1. Wenn ich über httpRequest.… im asynchron-Modus die Daten hole

    Warum willst du das tun?

    „Die[sic!] Fetch API bietet eine Schnittstelle zum Abrufen von Ressourcen (auch über das Netzwerk). Wer schon einmal mit XMLHttpRequest gearbeitet hat wird Ähnlichkeiten erkennen. Die[sic!] neue API bietet jedoch einen ganzen Satz leistungsfähigerer und flexiblerer Funktionen.“ [MDN]

    LLAP 🖖

    --
    Wenn der Faschismus wiederkommt, wird er nicht sagen: Hallo, ich bin der Faschismus! Sondern er wird sagen: Ich nehme die Wahl an.
    1. Hallo,

      die "Gegenstelle" ist schon vorhanden und kann nicht verändert werden. Deshalb habe ich ein Beispiel mit XMLHttpRequest bekommen, das ich anpassen soll/kann.

      Ist dann die "Fetch API" komplett "kompatible", wenn die Gegenstelle, wie auch immer, eine Anfrage per XMLHttpRequest erwartet ?

      Beispiele finde ich nur für XMLHttpRequest. Ist also noch "gängig" Wo kann ich Beispiele über die Fetch API finden ? Ich bin ja gerne bereit was neues zu benutzen.

      Danke

      1. Beispiele finde ich nur für XMLHttpRequest. Ist also noch "gängig"

        Durchaus.

        Wo kann ich Beispiele über die Fetch API finden ? Ich bin ja gerne bereit was neues zu benutzen.

        Wie fast alles im MDN

        (hoffe dort ist alles korrekt, ich habe das nicht durchgelesen und bevorzuge eigentlich die englische Version (oft aktueller und ausführlicher)

        --
        Stur lächeln und winken, Männer!
        1. Hallo,

          was natürlich durch die vielen Parameter die ich übergeben/einstellen kann optimal macht, macht es für den Anfang schwieriger für mich.

          Ich mach mal ein Beispiel.

          ich habe die url "dfnsdfhkhsdkjysd/test.cgi"

          Dieser url muss ich einen Parameter z.B. "Funktionstest" übergeben, damit ich "OK" (Textform) zurück bekomme.

          Wie müsste ich hier vorgehen ? .... mein Ansatz ....

           fetch(url + "?" + "Funktionstest")
               .then((response) => ergebnis = response.text()
          

          So einfach wird es nicht sein ... auch schon wegen timeout usw.

          Danke für die Hilfe

          1. Hallo piet,

            welchen Timeout meinst du? Der Browser sollte einen zu lange laufenden Request von sich aus nach einer gewissen Zeit abbrechen - willst Du diese Zeit beeinflussen oder fragst Du, wie Du auf dieses Szenario mit fetch reagieren kannst?

            Die Antwort auf letzteres wäre .catch, die Antwort auf ersteres ist kompliziert, weil Fetch das kompliziert löst. Lektüre wäre die MDN, Stichwort AbortSignal. Da ist auch ein Beispiel.

            Rolf

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

              fetch war ein super Tip von Dir, das geht wirklich einfach.

              Wenn keine Verbindung zustande kommt, möchte ich das gezielt auswerten. Ich werde es mit catch probieren ...

              Irgendwie sitze ich aber gerade auf der Leitung und finde auch nichts passendes im Netz.

              Wie werte ich response aus ? Ich bekomme im response (value) z.B. "Angeforderter Name":"Zahlenwert" zurück.

              Wie kann ich gezielt auf den "Zahlenwert" über den "Angeforderter Name" zugreifen ?

              wert: Promise { "fulfilled" }
              ​
              <state>: "fulfilled"
              <value>: {…}
              ​​Z_leistung_AG: "1133656862"
              ​​<prototype>: {…}
              ​<prototype>: PromiseProto
              
              

              ... So sieht das Object im Debugger aus

              Bei httpRequest hattte ich es so gelöst

              response = eval('('+httpRequest.responseText+')');
              i =parseInt(eval('response.' + varname));
              

              Wie gesagt ... ich sitze gerade auf der Leitung 😅

              Danke

              1. Bei httpRequest hattte ich es so gelöst

                response = eval('('+httpRequest.responseText+')');
                i =parseInt(eval('response.' + varname));
                

                Grottenschlecht eine Response an eval zu übergeben! Und wenn die Response schon ein JSON'String ist, dafür gibt es JSON.parse().

                MFG

              2. Hallo piet,

                fetch war ein super Tip von Dir,

                Das ist nicht meine Häuptlingsfeder - damit kann ich mich nicht schmücken.

                Die erste .then Methode bekommt ein Response-Objekt, nicht den Response-Text. Du hast dann die Möglichkeit, Methoden dieses Objekts zu nutzen um die Response in ein von Dir erwarteten Format zu bringen.

                Fetch Zugriffe baut man nach diesem Pattern:

                fetch(url, init)
                .then(response => response.json())
                .then(json => ...)
                .catch(error => ...);
                

                json ist eine der Methoden des Response-Objekts, um die empfangene Antwort in die gewünschte Form zu bringen. Unser Wiki hält sich da ziemlich bedeckt bzw. verweise auf die entsprechende Seite bei MDN.

                Für die Frage, was genau man tun muss, müsstest Du diese Frage beantworten: Was GENAU kommt da zurück?

                foo: "Bar"
                

                oder

                { foo: "Bar" }
                

                Abhängig davon muss man schauen wie man weitermacht.

                Rolf

                --
                sumpsi - posui - clusi
                1. Hallo,

                  hat alles wunderbar funktioniert. Ich konnte die Variable mit eval('wert.' + var_name) auslesen, wobei "wert" mein Objekt ist und in "var_name" der "Variablenname" steht.

                  Vielen Dank an alle ... wieder viel gelernt ...

                     piet
                  
                  1. Hallo piet,

                    bitte bleibe nicht dabei. EVAL IS EVIL - in PHP und JavaScript gleichermaßen. Du bekommst diesen String von einem Fremdsystem und musst ihm darum misstrauen. Mit EVAL kann im Zweifelsfall beliebiger Code im Browser des Users ausgeführt werden.

                    Abgesehen davon ist die Zeile eval('wert.'+var_name) für die Javascript-Engine eine Katastrophenzone. Im Normalfall kann der Just-in-time Compiler deinen Code beim Laden einmal compilieren und optimieren, aber einen eval geht das nicht. Welche Kollateralschäden das für die Compilierung des Gesamtscripts hat, kann ich nicht absehen.

                    Es geht fast immer besser. Wenn die Variable wert ein Objekt enthält und Du daraus eine Eigenschaft auslesen willst, deren Name in var_name steht, dann brauchst Du kein eval. Das geht viel einfacher mit der Array-Syntax:

                    var_wert = wert[var_name];
                    

                    Rolf

                    --
                    sumpsi - posui - clusi
      2. @@piet

        Ist dann die "Fetch API" komplett "kompatible", wenn die Gegenstelle, wie auch immer, eine Anfrage per XMLHttpRequest erwartet ?

        Nein, die Gegenstelle erwartet eine Anfrage per HTTP. Davon, wie diese auf der Clientseite erstellt wird, bekommt die Gegenstelle nichts mit.

        Beispiele finde ich nur für XMLHttpRequest. Ist also noch "gängig"

        Um IE zu unterstützen, vielleicht. Ich würde aber eher das Fetch-API mit Polyfills verwenden.

        LLAP 🖖

        PS: BTW, du plenkst. Im Deutschen steht (wie in den meisten Sprachen; Französisch bildet eine Ausnahme) kein Leerzeichen vor dem Fragezeichen.

        --
        Wenn der Faschismus wiederkommt, wird er nicht sagen: Hallo, ich bin der Faschismus! Sondern er wird sagen: Ich nehme die Wahl an.
  2. Bitte beachten Sie die Same Origin Policy. D.h., mit XMLHttpRequest feuert man nicht einfach so einen Request auf irgendeine IP Adresse. Egal ob synchron oder asynchron.

    MFG

  3. damit ich weiß welcher callback-Aufruf zu welchem Parameter/IP-Satz gehört ?

    Sowas löst man über Parameter im Request und natürlich muss man auch dafür sorgen daß es serverseitig unterstützt wird.

    MFG

    1. Hallo pl,

      wenn Du meinst, dass man an das XmlHttpRequest Objekt Fremddaten anklebt - ja, kann man machen. Ist aber eigentlich nicht nötig.

      Piet schrieb:

      Wenn ich über httpRequest.open("get",ip_adresse[i] + "?" + var_name[i],true); im asynchron-Modus die Daten hole, kann ich dem callback-Programm einen Parameter mitgeben ?

      Beispiel: httpRequest.onreadystatechange = updatePage(schleifenzaehler); Wäre so etwas möglich, damit ich weiß welcher callback-Aufruf zu welchem Parameter/IP-Satz gehört ?

      Das ist eigentlich genau die richtige Idee, aber vielleicht nicht so gemeint gewesen. Wichtig zu wissen ist, dass JavaScript die updatePage-Funktion beim Registrieren des Eventhandlers aufruft, und nicht beim Ändern des readystate. Das ist aber gerade gut so. Der Trick für richtiges Funktionieren ist, dass updatePage eine Funktion höherer Ordnung sein muss, d.h. eine Funktion, die eine Funktion als Ergebnis zurückgibt. Diese Funktion ist dann der readystatechange-Eventhandler.

         for (let i=0; i<10; i++) {
            let req = new XmlHttpRequest();
            req.onreadystatechange = updatePage(req, i);
            req.open(...);
            req.send(...);
         }
      
      // und anderswo
      
         function updatePage(request, nummer) {
            return function() {
               // arbeite mit request und nummer
            }
         }
      

      Ich habe tatsächlich keine zuverlässige Quelle gefunden, die angibt, ob der readystatechange-Handler garantiert bestimmte Parameter bekommt, oder ob er in this einen bestimmten Wert vorfindet. Manche erwarten, dass das request-Objekt in this steht, andere erwarten, dass es als erster Parameter übergeben wird. Eine andere Quelle bestritt, dass es irgendwelche Garantien gäbe. Darum bin ich den sichersten Weg gegangen: Ich gebe Request UND Nummer in die updatePage-Funktion hinein.

      Auf diese Weise wird bei jedem Schleifendurchlauf eine neue Closure gebildet, die den Request und den Schleifenzählerstand enthält, und innerhalb dieser Closure läuft dann die zurückgegebene Funktion ab, kann das Event behandeln und hat den korrekten Request und den korrekten Schleifenzähler zur Verfügung.

      Rolf

      --
      sumpsi - posui - clusi
      1. wenn Du meinst, dass man an das XmlHttpRequest Objekt Fremddaten anklebt

        Ne das meine ich eben nicht. Ich schrieb Parameter im Request, das ist HTTP.

        MFG

        1. Hallo pl,

          willst du im readystatechange Handler die URL analysieren, die Du verschickt hast? Das ist zum einen lästig, und zum anderen brauchst Du dafür das XMLHttpRequest Objekt. Wie ich oben schrieb, ist das nicht so GANZ trivial, wenn man mehrere Requests parallel feuert. Und wenn man eh schon eine Closure schürt, dann kann man auch noch ein paar Parameter dranknoten.

          Rolf

          --
          sumpsi - posui - clusi
          1. Sorry ich dachte der Parameterbegriff sei klar. Man kann Parameter an das URL hängen oder im Messagebody oder Header senden und damit dem Request eine Identität verpassen. Und diese Identität natürlich auch in der Response zurückschicken. MFG

            1. Hallo pl,

              ah - das meintest Du mit "der Server muss es unterstützen". Kann man machen, ja, aber warum soll ein Server wissen müssen, was ein Client für seine eigene Steuerung braucht? Entkoppelung buchstabiere ich anders.

              Rolf

              --
              sumpsi - posui - clusi
              1. aber warum soll ein Server wissen müssen, was ein Client für seine eigene Steuerung braucht?

                Das muss ein Server immer wissen. Z.B. um einen bestimmten Content-Type zu senden betrachtet der Server den Accept-Header.

                MFG

                1. Hallo pl,

                  nein - das habe ich nicht gemeint. Natürlich muss der Server wissen, was der Client von ihm haben möchte. Aber er sollte nicht wissen, wie der Client seine Verarbeitung steuert. Das Durchschleifen eines Steuerparameters ist unter diesem Gesichtspunkt nicht korrekt.

                  Es ist Sache des Clients, seine Requeste zu managen und auf jeden richtig zu reagieren. Dafür darf er keine Serverhilfe beanspruchen. Auf die kann er sich nicht verlassen. Beispiel: ich habe 10 Bereiche auf meiner Seite - für jeden schicke ich eine Request ab um die Daten dafür zu bekommen. 5 davon gehen schief und laufen auf HTTP 404 oder HTTP 500 oder sonst was in der Art. In welchem Bereich zeige ich den Fehler nun an?

                  Rolf

                  --
                  sumpsi - posui - clusi
                  1. In diesem Fall muss man sich sogar darauf verlassen, daß der Server das Orign akzeptiert, siehe hier

                    MFG

      2. Ein req.onreadystatechange findet 3 oder 4 mal statt, also mehrmals und wie der Name bereits vermuten lässt bei jeder Änderung des xhr.readyState

        MFG