提问者:小点点

如何通过socket.io将一个节点js后端上的集合发送到前端?


似乎 socket.io 从节点js后端发送到前端时将集合转换为空对象。为什么会这样?它是 JSON 的限制、套接字中的错误还是节点 js 中的错误?

在前端,我只是做了一些类似< code>socket.on('room ',(data) =的事情

在我的节点服务器中,我尝试过这样做:

const set = new Set;
set.add("Test");
console.log(set); // outputs as: Set { 'Test' }
mySocketIoNameSpace.emit('room', set); // ends up on the front end as an empty object {}

…这不起作用。尽管这很好:

const arr = new Array();
arr.push("Test");
mySocketIoNameSpace.emit('room', arr); // front end gets: ["Test"]

const obj = new Object();
obj["Test"] = true;
mySocketIoNameSpace.emit('room', obj); // front end gets: {Test: true}

我想我必须发出类似< code>Array.from(set)的东西,或者只使用一个数组或对象,而不是集合,这看起来很不幸,因为这会降低集合的速度或唯一性。


共2个答案

匿名用户

节点.js发送 JSON。如果将 Set 转换为 JSON,则会忽略其值,因为它们不会存储为属性。因此,您可以将其转换为数组,也可以使用类似以下内容:

function Set_toJSON(key, value) {
  if (typeof value === 'object' && value instanceof Set) {
    return [...value];
  }
  return value;
}

来自@tanguy_k帖子的代码片段

匿名用户

从服务器向客户端发送对象通常是通过JSON完成的,如果您传递任何类型的对象,socket.io的. emit()将尝试这样做。

但是,JSON无法表示Set对象或任何其他较新的Javascript集合对象,如MapWeakMap等。。。

幸运的是,集合实际上只是键的平面集合,可以直接表示为数组。接收者可以自己将它作为一个数组使用,也可以在收到它时将其转换为一个集合。

因此,要将其作为数组发送,您可以这样做:

 mySocketIoNameSpace.emit('room', [...set]); 

而且,收件人,可以把它转换成这样的集合:

socket.on('room', function(data) {
    if (Array.isArray(data)) {
        data = new Set(data);
    }
});

你第一次尝试的原因:

mySocketIoNameSpace.emit('room', set);

不起作用是因为 socket.io 只是直接将 set 变量传递给 JSON 转换器,而 JSON 转换器(没有 Set 对象的专业知识)只是将其视为没有可枚举属性的常规 Javascript 对象,因此除了空对象之外,它没有什么可放入 JSON 的。如果要列出 Set 对象的可枚举属性,则找不到任何属性。