Olli: Rückmeldung nach Dateiladevorgang

Hallo Allerseits!

Ich habe eine Problemstellung, zu der ich im WWW nichts gefunden habe und brauche daher die Unterstützung der Profis...

Folgende Aufgabe:
Es existiert ein Button.
Wenn dieser angeklickt wird, wird ein PHP-Script ausgeführt.
Da dieses sehr rechenintensiv ist, soll der Benutzer eine Art "Ich bin beschäftigt"-Feedback erhalten, solange der Vorgang läuft.
Ich dachte da zuerst an eine Veränderung des Cursors.
Dies geht ja recht einfach mit z.B.

  
document.body.style.cursor='wait';  

Soweit so gut.

Der vollständige Code lautet:

  
document.body.style.cursor='wait';  
window.location.href = "../Verzeichnis/datei.php";  
document.body.style.cursor='default';  

In der 1. Zeile wird der Cursor auf "busy" gesetzt.
In der 2. Zeile wird das PHP-Skript geladen.
Und in der 3. Zeile der Cursor dann wieder zurück gesetzt.

Leider funktioniert dies nicht, da die JavaScript-Zeilen einfach hintereinander weg abgearbeitet werden. Will heißen, Zeile 3 wird ausgeführt, obwohl der Befehl in Zeile 2 noch nicht vollständig abgearbeitet wurde.

Ich habe deshalb mit Ajax experimentiert. Über das XMLHttpRequest-Objekt kann man ja eine Rückmeldung vom Server erhalten, wann dieser mit der Abarbeitung fertig ist.
Dies funktioniert nur bedingt. Ich erhalte zwar nach der Abarbeitung über den HTTP-Statuscode die Antwort 200 (für Ok), aber das Ergebnis der Abarbeitung wird nicht an den Client gesendet (das PHP-Skript erzeugt eine Excel-Datei, die an den Client gesendet wird).

Da ich mit meinem "Latein" am Ende bin, hier der Post und die Frage an Euch, ob ihr eine Idee habt.

  1. Hi,

    Wenn dieser angeklickt wird, wird ein PHP-Script ausgeführt.
    Da dieses sehr rechenintensiv ist, soll der Benutzer eine Art "Ich bin beschäftigt"-Feedback erhalten, solange der Vorgang läuft.
    Ich dachte da zuerst an eine Veränderung des Cursors.
    Dies geht ja recht einfach mit z.B.

    document.body.style.cursor='wait';

    
    > Soweit so gut.  
      
    Wozu eigentlich?  
    Mein Browser zeigt diesen Cursor eh automatisch an, so lange er noch auf Daten vom Server wartet.  
      
    
    > Ich habe deshalb mit Ajax experimentiert. Über das XMLHttpRequest-Objekt kann man ja eine Rückmeldung vom Server erhalten, wann dieser mit der Abarbeitung fertig ist.  
    > Dies funktioniert nur bedingt. Ich erhalte zwar nach der Abarbeitung über den HTTP-Statuscode die Antwort 200 (für Ok), aber das Ergebnis der Abarbeitung wird nicht an den Client gesendet (das PHP-Skript erzeugt eine Excel-Datei, die an den Client gesendet wird).  
      
    Wenn du das Script per AJAX aufrufst, dann ist es auch dein JavaScript, das die Antwort im Hintergrund erhält.  
      
    MfG ChrisB  
      
    
    -- 
    “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
    
    1. Hi,

      Hi ChrisB,

      Wenn dieser angeklickt wird, wird ein PHP-Script ausgeführt.
      Da dieses sehr rechenintensiv ist, soll der Benutzer eine Art "Ich bin beschäftigt"-Feedback erhalten, solange der Vorgang läuft.
      Ich dachte da zuerst an eine Veränderung des Cursors.
      Dies geht ja recht einfach mit z.B.

      document.body.style.cursor='wait';

      
      > > Soweit so gut.  
      >   
      > Wozu eigentlich?  
      > Mein Browser zeigt diesen Cursor eh automatisch an, so lange er noch auf Daten vom Server wartet.  
      
      Bei mir nicht. Weder im FF noch im IE.  
      Aber das grundsätzliche Problem ist ja, dem Benutzer zu signalisieren, dass da jetzt etwas längert dauert und diesem dies mitzuteilen. Ob nun mit einer Cursoraktion, oder einer anderen Meldung. Diese "Signalisierung" soll solange aktiv sein, bis das Skript/die Berechnung fertig ist.  
        
      
      > > Ich habe deshalb mit Ajax experimentiert. Über das XMLHttpRequest-Objekt kann man ja eine Rückmeldung vom Server erhalten, wann dieser mit der Abarbeitung fertig ist.  
      > > Dies funktioniert nur bedingt. Ich erhalte zwar nach der Abarbeitung über den HTTP-Statuscode die Antwort 200 (für Ok), aber das Ergebnis der Abarbeitung wird nicht an den Client gesendet (das PHP-Skript erzeugt eine Excel-Datei, die an den Client gesendet wird).  
      >   
      > Wenn du das Script per AJAX aufrufst, dann ist es auch dein JavaScript, das die Antwort im Hintergrund erhält.  
      
      Aber warum funktioniert die Rückmeldung dann ohne JavaScript?  
      ~~~javascript
        
      window.location.href = "../Verzeichnis/datei.php";  
      
      

      MfG ChrisB

      VG Olli

      1. Hallo,

        Wenn du das Script per AJAX aufrufst, dann ist es auch dein JavaScript, das die Antwort im Hintergrund erhält.
        Aber warum funktioniert die Rückmeldung dann ohne JavaScript?

        es funktioniert "ohne Javascript" ebenso wie mit: Ein Request geht an den Server, nach kurzer Zeit kommt die Antwort zurück. Im einen Fall interpretiert der Browser direkt, was da kommt, und leitet die entsprechende, für diesen MIME-Typ konfigurierte Aktion ein; im anderen Fall wird die Handler-Funktion aufgerufen, die in deinem XHR-Objekt vermerkt ist.
        Die empfangenen Daten hast du dann als String in deinem Javascript.

        Für das, was du vorhast (Anfordern einer Ressource und speichern derselben als Datei) ist AJAX aber prinzipiell ungeeignet, weil Javascript keinen Zugriff auf das Filesystem hat und die empfangenen Daten daher nirgends speichern kann.
        AJAX ist gedacht, um Daten vom Server abzurufen und damit *innerhalb des Dokuments* irgendwas anzustellen. Nicht außerhalb.

        So long,
         Martin

        --
        Er:  Mit wem warst du gestern abend aus?
        Sie: Du bist mal wieder eifersüchtig wie immer!
        Er:  Wer ist Immer?
  2. hi,

    Da ich mit meinem "Latein" am Ende bin, hier der Post und die Frage an Euch, ob ihr eine Idee habt.

    Na Du musst das schon an der richtigen Stelle tun, verstehe den asynchronen Request.

    Du hast
    xhr.onreadystatechange = rx; // <- Empfangsfunktion

    Innerhalb der Empfangsfunktion wird xhr.readyState und xhr.status abgefragt. Wenn xhr.status == 200 wird die callback-Funktion gefufen. Hierzu _muss_ es im Scriptbereich Deiner Datei eine callbackfunktion geben und: alles was nach Erhalt der Response gemacht werden soll, muss innerhalb der callback-Funktion passieren.

    Summa:
    Request senden, Gauge auf "Anfrage läuft" setzen
    Response flattert rein, es greift die callbackFunktion. Hier drinne setzt Du die Gauge auf "OK, hab alles".

    Gauge: Ein fiktives Objekt, was dem Besucher den Stand der Dinge anzeigt.

    Auf meiner Site findest Du massenhaft Beispiele zu Ajax und auch ein kleines aber feines Framework.

    Hotti

    --
    Wenn der Kommentar nicht zum Code passt, kann auch der Code falsch sein.
    1. hi,

      Hallo Hotti,

      Da ich mit meinem "Latein" am Ende bin, hier der Post und die Frage an Euch, ob ihr eine Idee habt.

      Na Du musst das schon an der richtigen Stelle tun, verstehe den asynchronen Request.

      Du hast
      xhr.onreadystatechange = rx; // <- Empfangsfunktion

      Innerhalb der Empfangsfunktion wird xhr.readyState und xhr.status abgefragt. Wenn xhr.status == 200 wird die callback-Funktion gefufen. Hierzu _muss_ es im Scriptbereich Deiner Datei eine callbackfunktion geben und: alles was nach Erhalt der Response gemacht werden soll, muss innerhalb der callback-Funktion passieren.

      Summa:
      Request senden, Gauge auf "Anfrage läuft" setzen
      Response flattert rein, es greift die callbackFunktion. Hier drinne setzt Du die Gauge auf "OK, hab alles".

      Gauge: Ein fiktives Objekt, was dem Besucher den Stand der Dinge anzeigt.

      Auf meiner Site findest Du massenhaft Beispiele zu Ajax und auch ein kleines aber feines Framework.

      Es ist natürlich genauso wie Du sagst:
      Das "Zurückändern" des Cursors muss natürlich in der Callback-Funktion stattfinden. Dann wird dieser auch erst dann auf "default" zurück gesetzt, wenn der Server xhr.status == 200 meldet. Das funktioniert prima. Ursprüngliches Problem gelöst ;-)
      Was ich aber mit Ajax nicht hinkriege ist, dass das aufgerufene PHP-Skript die fertige Excel-Datei an den Browser sendet und sich ein Browserfenster öffnet, dass fragt, ob die Excel-Datei gespeichert oder geöffnet werden soll.
      Mit dem ursprünglichen JavaScript-Code, d.h. ohne Ajax, ging das:

        
      window.location.href = "../Verzeichnis/datei.php";  
      
      

      Wie kann ich das mit dem Dateiaufruf via Ajax erreichen?
      Das PHP-Skript wird zwar aufgerufen und abgearbeitet, aber die Audgabe läuft irgendwie in Leere.
      Was mache ich da falsch?

      Hotti

      Olli

      1. hi,

        Was ich aber mit Ajax nicht hinkriege ist, dass das aufgerufene PHP-Skript die fertige Excel-Datei an den Browser sendet und sich ein Browserfenster öffnet,

        Das krieg ich auch nicht hin, weil: Die Ajax-Response geht nicht an den Browser sondern an das XHR-Objekt und über die Callbackfunktion wird die Response erstmal im DOM entgegengenommen und kann dann einem Bereich bzw. einem Element oder Object im Dokument selbst zugewiesen bzw. übergeben werden.

        Falls das Objekt im Dokument so beschaffen ist, dass es eine Exceldatei darstellen kann, ist das ok, also wenn es sowas gäbe (ein Plugin, ein Aplet). Es wird jedoch den Browser nicht dazu bewegen eine Datei unbekannten Typs zum Speichern Unter... anzubieten, denn der Browser hat bis jetzt immer noch nur einen Content-Type bekommen, wahrscheinlich text/html.

        Mit location.href hingegen wirst Du den Browser selbst dazu bewegen, die Location zu ändern mit möglicherweise einem anderen Content-Type als text/html, dazu jedoch brauchst Du keine Ajax-Response mit den Daten, die der Browser dann in einer anderen Location vorfindet wo er sie erneut downloaden wird und wenn für ihn nicht darstellbar, zum Speichern Unter... anbieten wird.

        Na, Olli, überschlaf das mal ;-)

        Horst Hackeblitz-Wexelberger (mit Bindestrich)

        --
        ^double dash.
        1. hi,

          Hi,

          Was ich aber mit Ajax nicht hinkriege ist, dass das aufgerufene PHP-Skript die fertige Excel-Datei an den Browser sendet und sich ein Browserfenster öffnet,

          Das krieg ich auch nicht hin, weil: Die Ajax-Response geht nicht an den Browser sondern an das XHR-Objekt und über die Callbackfunktion wird die Response erstmal im DOM entgegengenommen und kann dann einem Bereich bzw. einem Element oder Object im Dokument selbst zugewiesen bzw. übergeben werden.

          Falls das Objekt im Dokument so beschaffen ist, dass es eine Exceldatei darstellen kann, ist das ok, also wenn es sowas gäbe (ein Plugin, ein Aplet). Es wird jedoch den Browser nicht dazu bewegen eine Datei unbekannten Typs zum Speichern Unter... anzubieten, denn der Browser hat bis jetzt immer noch nur einen Content-Type bekommen, wahrscheinlich text/html.

          Mit location.href hingegen wirst Du den Browser selbst dazu bewegen, die Location zu ändern mit möglicherweise einem anderen Content-Type als text/html, dazu jedoch brauchst Du keine Ajax-Response mit den Daten, die der Browser dann in einer anderen Location vorfindet wo er sie erneut downloaden wird und wenn für ihn nicht darstellbar, zum Speichern Unter... anbieten wird.

          das ist wenigstens mal 'ne Erklärung, warum das mit Ajax nicht funktiniert.

          Ajax kam ja nur in Betracht, weil es damit möglich ist, eine Rückmeldung nach der Abarbeitung des PHP-Skripts vom Server zu erhalten.
          Und das war ja das ursprüngliche Thema.
          Gibt es aus Deiner Sicht dafür überhaupt eine Möglichkeit?

          VG
          Olli

          1. Hi,

            das ist wenigstens mal 'ne Erklärung, warum das mit Ajax nicht funktiniert.

            Wenn dir das erst im Nachhinein und nach Erklärung deutlich wird - dann stürze dich bitte künftig etwas weniger schnell darauf.

            Ajax kam ja nur in Betracht, weil es damit möglich ist, eine Rückmeldung nach der Abarbeitung des PHP-Skripts vom Server zu erhalten.
            Und das war ja das ursprüngliche Thema.
            Gibt es aus Deiner Sicht dafür überhaupt eine Möglichkeit?

            Natürlich kannst du den Server in einem zweiten, *unabhängigen* Request fragen, ob er mit der Abarbeitung des anderen schon fertig ist.

            Dann brauchst du allerdings eine Möglichkeit, eine Verbindung zwischen den beiden Requests herzustellen - Sessions wären bspw. eine Möglichkeit dazu. (Wobei man dann aufpassen muss, bei der Abarbeitung des lange daunernden Requests die Session nicht zu blockieren.)

            MfG ChrisB

            --
            “Whoever best describes the problem is the person most likely to solve the problem.” [Dan Roam]
  3. Hi,

    Leider funktioniert dies nicht, da die JavaScript-Zeilen einfach hintereinander weg abgearbeitet werden. Will heißen, Zeile 3 wird ausgeführt, obwohl der Befehl in Zeile 2 noch nicht vollständig abgearbeitet wurde.

    doch, wurde sie: Die Eigenschaft wurde gesetzt. Der Browser hat sogar schon mehr gemacht, er hat mit dem Laden der entsprechenden Seite begonnen! Wenn sie irgendwann da ist, wird der Mauszeiger übrigens wieder so sein, als hättest Du Dein JavaScript niemals ausgeführt - hast Du ja im Grunde auch nicht, es ist ja eine neue Seite da. Genau so, als hättest Du sie als Startseite im Browser eingestellt und diesen frisch gestartet.

    Ich habe deshalb mit Ajax experimentiert.

    Vielleicht solltest Du erst mal beschreiben, was eigentlich Dein Problem ist, anstatt nur auf Deine Fehlversuche einzugehen, mit denen Du dieses zu lösen versucht hast.

    Cheatah

    --
    X-Self-Code: sh:( fo:} ch:~ rl:| br:> n4:& ie:% mo:) va:) de:] zu:) fl:{ ss:) ls:~ js:|
    X-Self-Code-Url: http://emmanuel.dammerer.at/selfcode.html
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
    1. Hi,

      Hallo Cheatah,

      Leider funktioniert dies nicht, da die JavaScript-Zeilen einfach hintereinander weg abgearbeitet werden. Will heißen, Zeile 3 wird ausgeführt, obwohl der Befehl in Zeile 2 noch nicht vollständig abgearbeitet wurde.

      doch, wurde sie: Die Eigenschaft wurde gesetzt. Der Browser hat sogar schon mehr gemacht, er hat mit dem Laden der entsprechenden Seite begonnen! Wenn sie irgendwann da ist, wird der Mauszeiger übrigens wieder so sein, als hättest Du Dein JavaScript niemals ausgeführt - hast Du ja im Grunde auch nicht, es ist ja eine neue Seite da. Genau so, als hättest Du sie als Startseite im Browser eingestellt und diesen frisch gestartet.

      Natürlich funktioniert das Skript grundsätzlich, bzw. wird fehlerfrei abgearbeitet. Das ist nicht das Problem. Der Aussehen des Cursors wird nur schon zurück gesezt, bevor das PHP-Skript abgearbeitet ist. Dies soll aber erst danach passieren.
      Das was Du mit "niemals ausgeführt" und "neuen Seite" usw. meinst verstehe ich nicht.

      Ich habe deshalb mit Ajax experimentiert.

      Vielleicht solltest Du erst mal beschreiben, was eigentlich Dein Problem ist, anstatt nur auf Deine Fehlversuche einzugehen, mit denen Du dieses zu lösen versucht hast.

      Ich war der Meinung, dass ich das hinreichend beschrieben hätte.
      Was ist Dir unklar?

      Cheatah

      Olli