我正在用播放器周围的迷你地图制作浏览器游戏。我需要跟踪其他玩家的位置,并在有人移动时更新此迷你地图。我正在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