我正在用播放器周圍的迷你地圖製作瀏覽器遊戲。我需要跟蹤其他玩家的位置,並在有人移動時更新此迷你地圖。我正在NodeJS和CouchDB中實現它。我的設計如下:如何在NodeJS中模擬「睡眠」?
我有一個數據庫,用於所有不斷變化的遊戲數據。在這個數據庫中,我有一個包含二維數組中基本地圖數據的文檔,網格中的每個正方形都由此數組中的一個元素表示。由於我可以有大量不同的用戶同時在地圖上移動,所以我需要一些方法來確保我沒有像其他人寫信給它一樣讀取信息(如果大量用戶正在閱讀並且可以收到錯誤信息寫入單個文檔)。我決定在這個數據庫中有單獨的文件,代表各個方塊,每個文件都有「在」該方塊的球員以及與該方塊相關的一些其他數據。實質上,地圖文檔僅用作方形文檔的查找表。這使我可以更改單個文檔而不必重寫整個地圖文檔,解決了同時讀寫問題。
我的問題是,我需要獲取一個迷你地圖供用戶作爲參考。這個迷你地圖將有周圍廣場的文件。由於我同時需要所有這些,我認爲我只需從數據庫中抓取所有9個方格並將其返回到單個ajax響應中。我的問題雖然是減少我做的阻塞IO的數量。現在,我有一個嵌套的循環,請求從數據庫中需要的正方形。下面就來看看我的代碼(位置和地圖都傳遞):
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++;
});
}
}
我的問題,不過,是的getDoc是非阻塞的,所以我不知道什麼時候會設定方數據微縮。我想過做這樣的事情:
while(numDone < 9){
sleep(10);
}
callback(miniMap);
這將讓我等到CouchDB的完成我的所有數據,但JavaScript並沒有睡眠功能。我發現最接近的是setTimeout,但這也是非阻塞的,我絕對不會100%確定我選擇超時的時間足以讓CouchDB完成獲取我的數據。
所以基本上我想有一個條件,測試它,然後再返回到事件堆棧,如果條件爲false。我認爲唯一的解決辦法是有一個遞歸的setTimeout回調會做這樣的事情:
function testCallback(data, condition, callback){
if(data < condition){
setTimeout(function(){
testCallback(data, condition, callback);
}, 10);
}else{
callback(data);
}
}
這似乎是非常可怕的......有沒有更好的辦法,我可以這樣做呢?我是否應該放棄這種方法並強制要求多個Ajax調用來獲取更新的數據?我應該採取阻斷方法嗎?
我想我在做Map部分都是錯的。將所有內容保存在內存中而不是數據庫肯定是一種更簡單的方法。我想我會繼續並將所有內容都放入我的Map文檔中,並且只在需要重新啓動時才保存狀態。謝謝您的幫助!! – tjameson 2010-12-20 20:01:09
同時查看[Redis](http://redis.io/)。您啓動redis-server,然後在節點中使用redis模塊。你給一個字符串鍵和一個JSON對象,並且BAM保存所有的孩子和數據。加載它並使用該鍵再次將其作爲對象重新回到內存中。 – BigOmega 2012-12-28 04:18:07
對於此類型的狀態信息,您可能還會考慮將[Firebase](http://firebase.com)作爲Redis或關係數據存儲的替代方案。 Firebase將實時同步所有連接的客戶端。它專爲您的應用類型而設計。 – DrFriedParts 2013-07-09 22:52:37