Ankündigung

Einklappen
Keine Ankündigung bisher.

[Erledigt] AJAX-Request während Long-Polling

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • [Erledigt] AJAX-Request während Long-Polling

    Hallo.

    Ich arbeite momentan an einem Community-Script. Um Daten nahezu in Echtzeit anzeigen zu können, benutze ich Long-Polling.

    Der Browser sendet einen AJAX-Request an den Server, der dann solange da verbleibt, bis der Server neue Daten für den Browser hat oder die von mir angegebene 60-Sekunden-Zeitmarke erreicht ist.
    Sobald der Server neue Daten für den Browser hat oder die angegebenen Sekunden aufgebraucht sind, sendet der Server die neuen Daten, falls vorhanden, zurück, die aktuelle Verbindung wird getrennt und der Browser startet die nächste Anfrage und damit die nächste Verbindung.

    Dadurch besteht also fast stetig eine Verbindung zwischen Browser und Server.

    Während dieser Verbindung kann ich allerdings keine weiteren AJAX-Requests an den Server senden.

    Mir ist klar, dass Browser Limits haben, was parallele Verbindung zu einer Domain angeht, aber bei allen Statistiken, die ich zu dem Thema gefunden habe, ging hervor, dass alle Browser mindestens 2 parallele Verbindungen unterstützen.

    Mein Problem anhand eines Beispiels:

    - Die Seite wird geladen und damit das Long-Polling initialisiert
    - Ich drücke auf eine Schaltfläche zum Löschen eines Kommentars, wodurch ein AJAX-Request an den Server gesendet werden soll, der den entsprechenden Kommentar aus der Datenbank löscht
    - Der Request zum Löschen wird erst ausgeführt, nachdem die aktuelle Long-Polling-Verbindung wegen neuer Daten oder des Zeitlimits beendet wurde und quasi "zwischengeschoben", bevor die nächste Long-Polling-Anfrage gesendet wird

    Ich habe leider bei meinen Recherchen nicht herausfinden können, ob es ein Workaround oder sonstige Lösungen für dieses Problem gibt.

    Als lokalen Server nutze ich die Mac-Version von XAMPP 5.6.3-0. Die Konfigurationsdateien sind noch nicht bearbeitet worden.

    Ich hoffe, es wird ansatzweise klar und bedanke mich schon einmal für Eure Antworten!

    Viele Grüße

  • #2
    Ohne Code wirds wildes Raten. Könnte sein, dass du 2 mal das gleiche XHRRequest Object benutzt? Oder du lädst synchron nach? Oder...
    I like cooking my family and my pets.
    Use commas. Don't be a psycho.
    [URL="http://jscouch.de"]Blog[/URL] - [URL="http://coverflowjs.github.io/coverflow/"]CoverflowJS[/URL]

    Kommentar


    • #3
      Zitat von Lightshade Beitrag anzeigen
      - Der Request zum Löschen wird erst ausgeführt, nachdem die aktuelle Long-Polling-Verbindung wegen neuer Daten oder des Zeitlimits beendet wurde und quasi "zwischengeschoben", bevor die nächste Long-Polling-Anfrage gesendet wird
      Ist da eine Session im Spiel? Vielleicht blockiert die eine Verbindung die Session-Datei und die Lösch-Anfrage wartet dann bis die Datei wieder freigegeben wird?

      Kommentar


      • #4
        Ja, das Login-System basiert auf einer Session. Lediglich "session_start();", um die Nutzerstati über $_SESSION nutzen zu können. Aber ich wüsste nicht, wie ich prüfen kann, ob sich die Verbindungen gegenseitig behindern.

        Hier der besagte Code.

        Diese JavaScript-Datei wird standardmäßig im Head-Bereich als Modul eingebunden.

        Code:
        $(document).ready(function(e)
        {	
          function stream()
          {	
            var t;
        		
            $.ajax({
        	url: "core/stream.php",
        	type: "POST",
        	data: {'friendship_requests_count': $("#headerOptionFriendships").html()},
        	dataType: "JSON",
        	success: function(response){
        				
        	  clearInterval(t);
        				
        	  if(response.status == "results" || response.status == "no-results")
        	  {
        	    t = setTimeout(function(){ stream(); }, 1000);
        					
        	    if(response.status == "results")
        	    {
                      $("#headerOptionFriendships").html(response.streamData.friendship_requests.length);
        	    }
        	  }
        	},
        	error: function(response){
        				
        	  clearInterval(t);
        				
        	  t = setTimeout(function(){ stream(); }, 30000);
        	}
            });
          }
        	
          stream();
        });
        Und hier die stream.php-Datei.

        PHP-Code:
        <?php
            
        require_once('initialize.php');

            
        $time_wastet 0;
            
            
        $friendship_request_check mysql_query("SELECT * FROM `friendship` WHERE `receiver` = '$user_data[user_id]' AND `status` = 'sent'");
            
        $friendship_request_num_rows mysql_num_rows($friendship_request_check);
            
            if(
        $friendship_request_num_rows == $_POST['friendship_requests_count'] || $friendship_request_num_rows == 0)
            {
                while(
        $friendship_request_num_rows == $_POST['friendship_requests_count'] || $friendship_request_num_rows == 0)
                {
                    if(
        $time_wastet >= 60)
                    {
                        die(
        json_encode(array("status" => "no-results")));
                        exit;
                    }
                    
                    
        sleep(1);
                    
        $friendship_request_check mysql_query("SELECT * FROM `friendship` WHERE `receiver` = '$user_data[user_id]' AND `status` = 'sent'");
                    
        $friendship_request_num_rows mysql_num_rows($friendship_request_check);
                    
        $time_wastet += 1;
                }
            }
            
            if(
        $friendship_request_num_rows != $_POST['friendship_requests_count'])    
            {
                while(
        $row mysql_fetch_array($friendship_request_checkMYSQL_ASSOC))
                {
                    
        $friendship_requests[] = array("friendship_id" => $row['friendship_id'], "sender" => $row['sender'], "receiver" => $row['receiver']);
                }
            }
            
            die(
        json_encode(array("status" => "results""streamData" => array("friendship_requests" => $friendship_requests))));
        ?>
        Wenn ich dann einen weiteren AJAX-Aufruf starten möchte, kommt das im ersten Post genannte Problem auf.

        Beispielsweise:

        Code:
        $("body").on('click', '.activityCommentDeleteIcon', function()
        {
          var activityCommentContainer = $(this).closest(".activityCommentContainer");
        		
          $.ajax({
            url: "ajax/deleteComment.php",
            type: "GET",
            dataType: "JSON",
            data: {"comment_id": $(this).closest(".activityCommentContainer").children(".activityCommentId").val()},
            success: function(response){
              if(response.status == 'success')
              {
                triggerNotification("Der Kommentar wurde gelöscht.");
                activityCommentContainer.fadeOut(500);
              }
            }
          });
        });
        Wenn man's sich in der Entwicklungsumgebung von Chrome anschaut, steht während der bestehenden Verbindung bei "Status" und "Time" jeweils "Pending" als Info zur stream.php-Datei. Nach den vergangenen 60 Sekunden ohne neue Daten wird die Verbindung wie erhofft beendet, das in der Warteschlange stehende AJAX-Request zum Löschen eines Kommentars wird abgearbeitet, welches bei "Status" und "Zeit" auch solange "Pending" als Wert hat, solange die Verbindung zur stream.php-Datei besteht. Danach wird wieder an stream.php geajaxt.

        Funktionell läuft alles so, wie es soll, bis auf das besagte Problem.

        Kommentar


        • #5
          Zitat von Lightshade Beitrag anzeigen
          Ja, das Login-System basiert auf einer Session. Lediglich "session_start();", um die Nutzerstati über $_SESSION nutzen zu können.
          Versuch mal ein session_write_close() auszuführen bevor du dein Stream-Script in die Warteschleife schickst (ggf. noch benötige Werte aus $_SESSION anderweitig zwischenspeichern).

          Außerdem:
          - verwende nicht »SELECT *«, gib immer an welche Spalten du brauchst
          - die mysql_*-Funktionen sind veraltet, verwende mysqli bzw. PDO

          Kommentar


          • #6
            Es funktioniert tatsächlich alles, wenn ich am Anfang der stream.php-Datei session_write_close(); aufrufe.

            Ich hätte das Problem niemals darin erwartet, vielen Dank!

            Auf Dauer bemühe ich mich natürlich um eine sauberere Lösung.

            Kommentar


            • #7
              Hallöchen,

              die "saubere" Lösung besteht darin, einen eigenen, Datenbank-basierten Session-Handler zu implementieren. Das löst das Locking-Problem und macht das Streuen von session_write_close überflüssig.

              Viele Grüße,
              lotti
              [SIZE="1"]Atwood's Law: any application that can be written in JavaScript, will eventually be written in JavaScript.[/SIZE]

              Kommentar


              • #8
                Zitat von lottikarotti Beitrag anzeigen
                die "saubere" Lösung besteht darin, einen eigenen, Datenbank-basierten Session-Handler zu implementieren. Das löst das Locking-Problem
                Warum sollte ein Session-Handler, der in die Datenbank schreibt das Locking-Problem beheben? Ich vermute ja du ignorierst in deinem eigenen Session-Handler einfach das Locking und meinst dadurch kein Problem mehr zu haben.

                Kommentar


                • #9
                  Hallöchen,

                  Zitat von Blar Beitrag anzeigen
                  Warum sollte ein Session-Handler, der in die Datenbank schreibt das Locking-Problem beheben? Ich vermute ja du ignorierst in deinem eigenen Session-Handler einfach das Locking und meinst dadurch kein Problem mehr zu haben.
                  Deine Anmerkung, oder das worauf sie abzielt, ist natürlich korrekt. Ich hätte schreiben sollen, dass man das Problem damit vielmehr "umgeht", da die Datenbank sich von Natur aus nicht um parallele Lesezugriffe schert und hier erstmal kein Locking-Verhalten auftritt. Dass das bei Schreibzugriffen allerdings problematisch werden kann, steht außer Frage.

                  Viele Grüße,
                  lotti
                  [SIZE="1"]Atwood's Law: any application that can be written in JavaScript, will eventually be written in JavaScript.[/SIZE]

                  Kommentar

                  Lädt...
                  X