javascript - 对象或对象数组

标签 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'
        // ...
    }
]

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

最佳答案

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

不过,就性能而言,如果您经常倾向于通过对象的 ID 访问对象,则最好将其存储为键。您无需遍历集合中的每个元素即可通过其 ID 找到它。

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

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

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

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

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

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

删除比较棘手。当您“删除”或拼接一个数组时,拼接项之后的所有索引都会递减。然后,您还必须递减所有索引。你失去了性能。

更好的方法是不拼接数组,而是在删除它们时将套接字设置为“未定义”。这样,即使删除套接字,也不必更新索引。

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

如果您的应用程序长时间运行,您必须每大约 3000 个请求重建一次索引,因为“未定义”将开始膨胀您的套接字/索引数组。

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

此外,您可以使用我编写的库 ( affinity ),它是一个关系代数库。该库允许在对象集合上创建索引(很像在数据库中),因此您仍然可以拥有一个“正常”集合,同时对其进行基于索引的访问。

检查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').eq('29823')).first()

//...

关于javascript - 对象或对象数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34425343/

相关文章:

javascript - 成功 import-jdl 后,JHipster 实体菜单为空

arrays - es6 Mongoose 嵌套findById promise

node.js - Socket.IO 1.4.x 中的传输设置

node.js - 每当我发送消息时,它都会在 react 中多次显示相同的消息

javascript - D3js 图表未显示

javascript - 我的 'new Object' 会在套接字断开连接时被垃圾收集吗

javascript - 在这种情况下,比调解器模式更好的方法来解耦小部件?

javascript - 动态隐藏 ExtJS Fieldset 中的控件

javascript - Vue 中的 componentWillReceiveProps

node.js - SQLite 在 Windows 10 上无法与 Electron 和 Node 一起使用