Tach!
Ich würde nicht immer wieder das DOM rauf und runter abklappern, um zu ermitteln, welche Daten ich habe. Stattdessen nähme ich eine eigene Datenhaltung,
Doppelte Datenhaltung ist schlecht.
Das ist keine doppelte Datenhaltung. Das ist eine Datenhaltung in einem verarbeitbaren Format. Dass darin enthaltenen Daten zwecks Ausgabe oder anderer Verarbeitung an anderen Stellen vervielfältigt werden müssen, steht auf einem anderen Blatt. Gehalten zum Zwecke der Verwaltung werden sie nur einmal, in dem speziellen Objekt. Sie in der Gegend zu verteilen und dann diese Gegend ständig abzusuchen, das ist schlecht.
Selbst wenn ich das so machen würde, es würde das Problem nicht beheben. Der Laufzeitfehler wird zwar kleiner, aber er bleibt, weil sich asynchrone Requests überschneiden..
Es kommt zu keinem Fehler, weil jeder Datensatz zum einen eindeutig gekennzeichnet ist, und zum anderen sich durch diese eindeutige Kennzeichnung in einem quasi Unique Index des datenhaltenden Objekts keine Verdopplungen ergeben.
Mit Stand der Dinge tritt das geschilderte Problem sehr selten auf, ist aber immerhin möglich. Praktisch wird auch nicht das DOM rauf und runter abgeklappert sondern nur das Formular serialisiert um an die Liste der Nachrichtennummern zu kommen für den Request. Und wenn eine Response neue Nachrichten bringt, werden einfach nur <input>-Felder mit gleichem Namen an das Formular gehängt (mehrere gleichnamige Parameter bilden dann serverseitig ein Array mit den Valü's). Mehr Aufwand ist nicht gerechtfertigt.
Das liest sich jedenfalls nicht besonders gut. Warum müssen denn die Daten in ein Input mit allem drum und dran, wenn ein div genügt? Und wenn du wirklich keinen großen Aufwand haben möchtest, dann nimm AngularJS, verringere deinen Entwicklungsaufwand und lass den Aufwand von Angular erledigen.
Die Ausgabe sähe ungefähr so aus:
<body ng-app="chat">
...
<section ng-controller="messages">
<div ng-repeat="key in Object.keys(datenhaltung) | orderBy: 'toString()'">
<span>{{datenhaltung[key].time| date:'HH:mm:ss' }}</span>
<span>{{datenhaltung[key].sender}}</span>
{{datenhaltung[key].text}}
</div>
</section>
...
</body>
Ein Controller könnte so aussehen:
angular.module('chat', [])
.controller('messages', ['$scope', '$http', function($scope, $http) {
$scope.datenhaltung = {};
var now = new Date().getTime();
$scope.datenhaltung[now] = {
time: now,
sender: 'System',
text: 'Willkommen im Chat'
};
var poll = function() {
// nach einer Sekunde
$timeout(function () {
$http.post('/someUrl', {keys: Object.keys($scope.datenhaltung)}).
then(function(response) {
// Datenhaltung befüllen
// messages ist ein Array mit Message-Objekten wie oben bei der Begrüßung
angular.forEach(response.data.messages, function (message) {
$scope.datenhaltung[message.time] = message;
});
}, function(response) {
// hier Code für den Fehlerfall
});
poll();
}, 1000);
};
poll();
}]);
Das ist nur ein ausbaufähiges Grundgerüst, da fehlt noch das Drumherum, wie das Einbinden der Angular-Bibliothek und das Behandeln der Nutzer-Eingaben. Der Code soll zeigen, wie einfach und übersichtlich es gehen kann. Ich hab ihn einfach nur so dahingeschrieben, ohne ihn zu testen. Noch schöner wäre er unter Verwendung einer websocketbasierten Kommunikation geworden. Damit ergibt sich auch nicht das Problem des ständigen Pollens und Vergleichens, welche Nachrichten noch fehlen. Die kommen dann in der Reihenfolge, wie sie am Sever eintrudeln. Dafür gibt es auch fertige Bibliotheken inklusive Beispielen im Netz. (Auf die Schnelle gefunden: ... but in the meantime I had a look at AngularJS and knocked up a quick chat app to see how easy it would be. The answer was “very”.)
dedlfix.