Ich baue ein Browser-Spiel mit einer Mini-Karte der Umgebung des Spielers. Ich muss verfolgen, wo andere Spieler sind und diese Minikarte aktualisieren, wenn jemand sich bewegt. Ich implementiere das in NodeJS und CouchDB. Mein Entwurf geht wie folgt:Wie emulieren ich "Schlaf" in NodeJS?
Ich habe eine Datenbank für alle sich ändernden Spieldaten. In dieser Datenbank habe ich ein Dokument, das die grundlegenden Kartendaten in einem zweidimensionalen Array enthält, wobei jedes Quadrat auf dem Gitter durch ein Element in diesem Array dargestellt wird. Da ich viele verschiedene Benutzer haben konnte, die alle gleichzeitig auf der Karte waren, brauchte ich einen Weg, um sicherzustellen, dass ich nicht gelesen werde, während jemand anderes schreibt. Ich könnte fehlerhafte Informationen bekommen, wenn eine Menge Benutzer lesen und Schreiben in ein einziges Dokument). Ich entschloss mich, separate Dokumente in dieser Datenbank zu haben, die die einzelnen Quadrate repräsentieren, und jedes Dokument hat die Spieler, die auf diesem Quadrat "on" sind, und einige andere Daten, die mit diesem Quadrat verbunden sind. Im Wesentlichen wird das Kartendokument nur als Nachschlagetabelle für das quadratische Dokument verwendet. Dadurch kann ich ein einzelnes Dokument ändern, ohne das gesamte Kartendokument neu schreiben zu müssen, wodurch das Problem der gleichzeitigen Lese- und Schreibvorgänge gelöst wird.
Mein Problem ist, dass ich eine Mini-Map für den Benutzer als Referenz verwenden muss. Diese Minikarte enthält die Dokumente der umliegenden Plätze. Da ich das alles zur gleichen Zeit brauche, dachte ich, ich würde einfach alle 9 Quadrate aus der Datenbank holen und sie in einer einzigen Ajax-Antwort zurückgeben. Mein Problem ist jedoch mit der Verringerung der Menge an blockierenden IO, die ich mache. Im Moment habe ich eine verschachtelte Schleife, die die benötigten Quadrate von der Datenbank anfordert. Hier ist ein Blick auf meinen Code (Position und Karte sind vergangen in):
var miniMap = new Array();
var keyMap = new Object();
var numDone = 0;
for(i = position.y - 1, y = 0; i < position.y + 1 && i < map.length; i++, y++){
miniMap[i] = new Array();
for(v = position.x - 1, x = 0; v < position.x + 1 && v < map.length; v++, x++){
keyMap[map[i][v].id] = {'x': x, 'y': y};
gameDB.getDoc(map[i][v].id, function(er, doc){
var tPos = keyMap[doc._id];
miniMap[tPos.y][tPos.x] = doc;
numDone++;
});
}
}
Mein Problem ist jedoch, dass GetDoc ist nicht blockierend, so dass ich weiß nicht, wann es die quadratischen Daten zu Minimap gesetzt wird . Ich dachte an so etwas wie dies zu tun:
while(numDone < 9){
sleep(10);
}
callback(miniMap);
Dies lässt mich warten, bis CouchDB alle meine Daten fertig ist immer, aber JavaScript nicht über eine Sleep-Funktion. Der nächste, den ich gefunden habe, war setTimeout, aber das ist auch nicht blockierend und ich werde nie 100% ig sicher sein, dass die Zeit, die ich für die Zeitüberschreitung gewählt habe, ausreichen würde, dass CouchDB meine Daten abrufen kann.
Also im Grunde möchte ich eine Bedingung haben, testen, dann wieder an den Event-Stack zurückgeben, wenn die Bedingung falsch ist. Die einzige Lösung, die ich dachte, war eine rekursive SetTimeout Rückruf zu haben, die so etwas tun würde:
function testCallback(data, condition, callback){
if(data < condition){
setTimeout(function(){
testCallback(data, condition, callback);
}, 10);
}else{
callback(data);
}
}
Diese ziemlich schrecklich scheint ... Gibt es eine bessere Art und Weise, dass ich dies tun könnte? Sollte ich diesen Ansatz aufgeben und dort mehrere Ajax-Aufrufe erzwingen, um aktualisierte Daten zu erhalten? Soll ich einen blockierenden Ansatz wählen?
Ich nehme an, ich mache den Map Teil alles falsch. Alles in den Speicher anstatt in die Datenbank zu behalten, ist definitiv ein einfacher Weg, Dinge zu tun. Ich denke, ich werde fortfahren und alles in mein Kartendokument legen und den Zustand nur speichern, wenn ich neu starten muss oder so. Danke für die Hilfe!! – tjameson
Überprüfen Sie auch [Redis] (http://redis.io/). Sie starten den Redis-Server und verwenden dann das Redis-Modul im Knoten. Sie geben einen String-Schlüssel und dann ein Json-Objekt und BAM alle Kinder und Daten gespeichert. Lade es hoch und benutze den Schlüssel, um es als Objekt wieder in den Speicher zu bekommen. – BigOmega
Sie könnten auch [Firebase] (http://firebase.com) als Alternative zu Redis oder einem relationalen Datenspeicher für diese Art von Statusinformationen in Erwägung ziehen. Firebase synchronisiert den Status in Echtzeit mit allen angeschlossenen Clients. Es wurde für Ihre Art der Anwendung entwickelt. – DrFriedParts