【问题标题】:Async/await: UnhandledPromiseRejectionWarning: RangeError: Maximum call stack size exceeded异步/等待:UnhandledPromiseRejectionWarning:RangeError:超出最大调用堆栈大小
【发布时间】:2021-09-30 03:10:40
【问题描述】:

在我的 socket.io 应用程序中,我试图将房间中的一组用户发送到客户端,以创建一个 ul 元素来显示房间中的所有用户。 docs 表示您可以使用以下代码返回给定命名空间和房间中的所有套接字实例:

// return all Socket instances in the "room1" room of the "admin" namespace
const sockets = await io.of("/admin").in("room1").fetchSockets();

但是,它涉及await,这是我不太熟悉的。我只是将代码块放在 async 函数中,我不确定这是不是最好的处理方式。

io.of('/game').on('connection', socket => {
    console.log(`Socket ID: ${socket.id}`);
    
    const cookies = cookie.parse(socket.handshake.headers.cookie || "");
    console.log(cookies);
    const currentUser = cookies['current_user'];
    const roomName = cookies['room_name'];

    socket.username = currentUser;

    console.log(`${socket.username} connected to room "${roomName}"`);
    socket.on('disconnect', () => {
        console.log(`${socket.username} disconnected from room "${roomName}"`);
        io.of('/game').in(roomName).emit('leave', socket.username);
    });

    socket.join(roomName);

    (async() => {
        const usersInRoom = await io.of('/game').in(roomName).fetchSockets();
        console.log(`Number of users connected: ${usersInRoom.length}`);
        io.of('/game').in(roomName).emit('join', { username: socket.username, users: usersInRoom });
    })();
});

当我尝试运行它时,我在控制台中收到以下错误:

(node:9872) UnhandledPromiseRejectionWarning: RangeError: Maximum call stack size exceeded
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:28:19)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:9872) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:9872) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

我尝试对此进行一些研究,发现this answer,它建议将代码包装在try-catch 块中。我已经这样做了:

(async() => {
    try {
        const usersInRoom = await io.of('/game').in(roomName).fetchSockets();
        console.log(`Number of users connected: ${usersInRoom.length}`);
        io.of('/game').in(roomName).emit('join', { username: socket.username, users: usersInRoom });
    }
    catch(e) {
        console.log(e);
    }
})();

但我仍然收到错误:

RangeError: Maximum call stack size exceeded
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:28:19)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)
    at hasBinary (<path>\node_modules\socket.io-parser\dist\is-binary.js:49:63)

我应该如何解决这个问题?任何帮助将不胜感激。

【问题讨论】:

  • 可能需要查看周边代码。那里没有什么不寻常的。有趣的是,您实际上遇到了“堆栈溢出”。
  • @DanielDuong 我已经编辑了问题。
  • 你不能通过 socket.io 发送变量usersInRoom。这是一个实际的 socket.io 数据结构列表,这些数据结构不能转换为 JSON 以通过 socket.io 发送,即使它能够通过 socket.io 发送,它对另一个也没有任何意义连接结束,因为这些是服务器端套接字对象,客户端无论如何都无法做任何事情。
  • 由于您无法将usersInRoom 发送给客户,请备份并描述您尝试使用该代码完成的工作,以便人们可以提出不同/更好的方法来解决该问题。
  • @jfriend00 我试图将连接到该房间的用户列表发送到客户端,以创建一个显示房间中所有用户的ul 元素。我是否应该使用 for 循环来遍历 usersInRoom 并创建一个用户名数组,然后将其发送给客户端?

标签: javascript node.js asynchronous async-await socket.io


【解决方案1】:

正如我们在 cmets 中所讨论的,您不能通过 socket.io 连接发送整个 socket.io 连接对象,因为它不能转换为 JSON。

如果您真正想要发送的只是您已附加到 socket.io 对象的username 属性列表,那么您可以创建一个仅包含这些用户名的数组。

改变这个:

io.of('/game').in(roomName).emit('join', { username: socket.username, users: usersInRoom });

到这里:

const usernameList = usersInRoom.map(s => s.username);
io.of('/game').in(roomName).emit('join', { username: socket.username, users:  usernameList});

【讨论】:

    猜你喜欢
    • 2019-05-20
    • 1970-01-01
    • 1970-01-01
    • 2015-10-24
    • 2015-12-29
    • 2017-12-27
    • 2020-12-06
    • 2018-02-06
    • 2020-06-28
    相关资源
    最近更新 更多