0

Ich habe kürzlich eine Chat-Funktion erstellt und bemerke einen seltsamen Fehler. Im Folgenden ist der Code verwende ich in meinem Controller:AngularJs Controller .appendChild() addiert jedes Mal, wenn die Ansicht besucht wird

myFirebase.on('child_added', function(snapshot) { 
    var msg = snapshot.val(); 
    var msgUsernameElement = document.createElement("b"); 
    msgUsernameElement.textContent = msg.user; 

    var msgTextElement = document.createElement("p"); 
    msgTextElement.textContent = msg.message; 

    var msgElement = document.createElement("div"); 
    msgElement.appendChild(msgUsernameElement); 
    msgElement.appendChild(msgTextElement); 

    document.getElementById("messages").append(msgElement); 
    }); 

Angenommen wir die Chat-Ansicht wird zum ersten Mal eingeben, wenn ich dann chatten, die .appendChild() arbeitet völlig in Ordnung und die typisierte Nachricht erscheint in den div "Nachrichten". Angenommen, wir verlassen die Chat-Ansicht und geben sie erneut ein und geben eine neue Chat-Nachricht ein und senden sie. Dann wird die .appendChild() -Ausgabe zweimal ausgeführt, und die gleiche Nachricht wird zweimal in den div-Nachrichten angezeigt. Dies wird linear fortgesetzt. Wenn wir zum fünften Mal den Controller erneut aufrufen und eine Nachricht senden, wird die Nachricht fünfmal an die div "messages" angehängt ... Was passiert hier?

Ich verwende das Ionic Framework und die fertige App-Vorlage 'Tabs'. Meine Chat-Funktion befindet sich im Chat-Details-Controller.

Antwort

2

Das Problem liegt daran, dass der Event-Handler zweimal hinzugefügt wird, sobald Sie die Chat-Seite zum ersten Mal besuchen und wenn Sie wiederkommen. Um das zu bestätigen, besuchen Sie es ein drittes Mal, und Sie sollten es 3x sehen.

Die Lösung besteht darin, einen $onDestroy Handler zu setzen, um den Event-Handler zu entfernen. Wenn der Event-Handler nicht entfernt werden kann (dh er hat keine off-Methode), sollten Sie eine Variable setzen, um Ihnen mitzuteilen, dass sie initialisiert ist, und Sie überprüfen dies beim Initialisieren der Seite (um zu verhindern, dass Sie es zweimal machen))

0

So Mikkel gab den richtigen Vorschlag, eine Variable zu initialisieren und grundsätzlich als Flag zu verwenden, um sicherzustellen, dass mein Ereignishandler bei mehrfacher Eingabe in die Chatansicht nicht mehrfach aufgerufen wird, sondern nur einmal. Das Folgende ist meine Lösung:

if (window.localStorage.getItem("notVisited") == null){ //This initilizes a variable in localstorage 
     window.localStorage.setItem("notVisited","true"); 
    } 

    var startListening = function() { 
    myFirebase.on('child_added', function(snapshot) { 
    var msg = snapshot.val(); 
    var msgUsernameElement = document.createElement("b"); 
    msgUsernameElement.textContent = msg.user; 

    var msgTextElement = document.createElement("p"); 
    msgTextElement.textContent = msg.message; 

    var msgElement = document.createElement("div"); 
    msgElement.appendChild(msgUsernameElement); 
    msgElement.appendChild(msgTextElement); 

    document.getElementById("messages").append(msgElement); 
    }); 
    window.localStorage.setItem("notVisited","false"); 
    } 
if (window.localStorage.getItem("notVisited") == "true") { 
    startListening(); 
} 

Jetzt, nach dieser Umsetzung, lief ich in ein neues Problem, das mit diesem neuen Code war, dass jedes Mal, wenn ich die Ansicht Wiedereintritt in den vorherigen Chat-Nachrichten nicht nach oben zeigen würden. So habe ich dies:

 if (window.localStorage.getItem("notVisited") == "false"){ 
$http({ 
    url: "https://uniff-f4136.firebaseio.com/" + chatKey + ".json", 
    method: "GET" 
    }).then(function (response) { 
     for (var i in response.data){ 
      var msgUsernameElement = document.createElement("b"); 
      msgUsernameElement.textContent = response.data[i].user; 

      var msgTextElement = document.createElement("p"); 
      msgTextElement.textContent = response.data[i].message; 

      var msgElement = document.createElement("div"); 
      msgElement.appendChild(msgUsernameElement); 
      msgElement.appendChild(msgTextElement); 

      document.getElementById("messages").append(msgElement); 
     } 
    }); 
} 

Am Ende, das ist mein Chat-Arbeit gemacht, obwohl ich nicht die Wiederholung von Code mögen. Ich hoffe, dass andere dies aufschlussreich finden. Abschließend erfahren Sie mehr über die Verwendung von Firebase zum Erstellen einer Echtzeit-Web-Chat-App: https://codelabs.developers.google.com/codelabs/cloud-firebase-chat/#4

+0

Sie können Ihren Code umgestalten, indem Sie den allgemeinen Code verwenden und ihn in eine Methode einfügen als Parameter und du wirst Recht haben. Sie können sich auch Meteor (http://meteor.com) ansehen, da es sich um einen Stack handelt, der für einfache reaktive Anwendungen (wie Chat) entwickelt wurde, Sie abonnieren einfach die Daten und Änderungen werden automatisch gesendet. – Mikkel

Verwandte Themen