对象或对象数组

时间:2015-12-22 22:15:39

标签: javascript node.js socket.io

我想在node.js中存储连接的套接字' id(socket.io)以及其他一些信息。 原因是,我必须列出客户及其信息,或者我必须通过它的ID找到一个。 我只能使用客户端连接时创建的socket对象。

我认为如果客户连接,我会把'它的ID和clients变量的附加信息。

var clients = /* this is the question */;

io.on('connection', function(socket) {
    // I can't use `io` just the `socket`
})

我对这个问题有两个想法,但我不知道哪个更好的结构可以做到这一点,或者如果很多客户连接的话会更快并且使用更少的内存?

对象

唯一ID是密钥,数据存储在其中。

{
    '01234': {
        // ...
    },
    '56789': {
        // ...
    }
}

对象数组:

对象存储在一个数组中,它们的唯一ID和数据也存储在它们中。

[
    {
        id: '01234'
        // ...
    },
    {
        id: '56789'
        // ...
    }
]

哪种性能和内存更快或更好? 或者还有其他解决方案吗?

2 个答案:

答案 0 :(得分:1)

两者都有优点和缺点。

使用对象:

{
    '01234': {
        // ...
    },
    '56789': {
        // ...
    }
}

只需调用sockets[socketId]或其他任何内容即可进行非常简单的查找。

如果您有一个集合([{},{},{}]),则每次要查找对象时都必须遍历集合:

var socketIWant = sockets.filter(socket => id === 0123)[0];
// or whatever

但是,“集合”模式非常常见,将数据保存在该结构中以使其更便于以后开发可能是值得的。

此外,如果您想使用数据库存储套接字信息,通常可以直接迭代服务器端集合并将其一对一存储到NoSQL数据库中。

如果您使用“对象对象”方法,则在查询或将对象保存到数据库时可能需要进行一些数据操作:

var sockets = { '0123': {} };

Objects.keys(sockets).forEach(function(key) {
  MyDB.save(_.assign(sockets[key], { _id: key }));
});

或类似上述内容。一些可能无关的“数据混乱”。从数据库中迭代和保存/查询(如果存在的话),收集方法会更简单一些。

答案 1 :(得分:1)

两种方法在内存方面几乎完全相同。在对象或对象数组中存储数据不会影响内存消耗。

性能方面,如果您经常倾向于通过ID访问对象,那么将其存储为密钥是个好主意。你不必循环遍历集合的每个元素,以便通过它的id找到它。

正如@Josh所说,你正在创建一个可能难以使用的非标准集合结构。

如果您担心这一点,可以创建一个外部索引。

sockets : [ {socket1}, {socket2}, {socket3} ]
indexes : { socket1 : 0, socket2 : 1, socket3 : 2 }

这样,要通过它的id访问套接字,你可以通过它存储在索引对象中的索引来获取它在数组中的位置。但是,您必须保持套接字数组和索引数组同步。

添加套接字很容易。您将套接字添加到数组,将id添加到索引。

socket.on('add', function(socket){
    var len = sockets.push(socket);
    indexes[socket.id] = len-1;
})

删除比较棘手。当你"删除"或拼接数组,拼接项后的所有索引都将递减。然后,您还必须减少所有索引。你的表现会失败。

更好的方法是不拼接数组,而是将套接字设置为" undefined"删除时。这样,即使删除套接字,也不必更新索引。

socket.on('delete' function(socket){
    sockets[indexes[socket.id]] = undefined;
    delete indexes[socket.id];
})

如果您的应用程序长时间运行,您必须每隔3000个请求重建索引,因为" undefined"将开始膨胀您的套接字/索引数组。

function rebuildIndex(){
    indexes = [];
    _.forEachRight(sockets, function(socket, index){
        if (_.isUndefined(socket)) sockets.splice(index, 1) 
        else indexes[socket.id] = index;
    })
}

此外,您可以使用我编写的库(affinity),这是一个关系代数库。这个库允许在对象集合上创建索引(就像在数据库中一样),所以你仍然可以有一个" normal"收集,同时对其进行基于索引的访问。

检查here是否有工作示例

var sockets = new affinity.Relation([
    {id : { type : affinity.Integer}}, 
    {socket : {type : affinity.Object}}
],[],{
    pk : 'id'
});

sockets.add(socket1);
sockets.add(socket2);

// then to have only the sockets array (to interact with db maybe)

var socketObjs = sockets.project(['socket']).elements()

这是在关系中定义套接字的简单方法。但是,您正在为id字段使用两倍的内存(因为它在套接字和ID列中重复)。如果需要,还可以为每个套接字的属性创建一个列,就像数据库表一样,以防止重复ID字段:

var sockets = new affinity.Relation([
    {id : { type : affinity.Integer}}, 
    {userId : {type : affinity.Integer}},
    {openedDate : {type : affinity.Date}},
    {token : {type : affinity.String}}
    // ...
],[],{
    pk : 'id'
});

//每个套接字都是关系中的一行。访问以下属性:

sockets.restrict(sockets.get(' ID&#39)当量(' 29823&#39))。第一()

// ...