Async/await: UnhandledPromiseRejectionWarning: RangeError: Maximum call stack size exceeded

Async/await: UnhandledPromiseRejectionWarning: RangeError: Maximum call stack size exceeded

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

// 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.

我试图对此进行一些研究,发现 ,这表明将代码包装在 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)

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

正如我们在评论中讨论的那样,您不能通过 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});