【问题标题】:try catch not working in Node socket.io listener尝试在 Node socket.io 侦听器中捕获不起作用
【发布时间】:2021-01-01 20:13:03
【问题描述】:

我正在开发一个涉及使用 WebSockets 的应用程序。我有以下代码作为应用程序的一部分:

io.on('connection', socket => {

   let PLAYER = {};

   // Listener for event 1
   // Listener for event 2
   // ...

   socket.on('setName', ({name, role, room}) => {

        PLAYER.name = name;
        PLAYER.role = role;
        PLAYER.room = room;

        try{
            joinRoom(PLAYER);  // This function can throw an error
            socket.emit('roomJoin');
        }catch(e){
            socket.emit('error', e.message);
            return;
        }
    });
});

现在,当 joinRoom 函数确实抛出错误时,Node 会崩溃并出现以下异常:

events.js:306
    throw err; // Unhandled 'error' event
    ^

Error [ERR_UNHANDLED_ERROR]: Unhandled error. ('error message')

error 事件永远不会发出。是什么导致 try catch 块失败?

注意:我使用的是 TypeScript,但已删除上述 sn-p 中的类型声明,因为它们与问题无关。

编辑 1:

我用更简单的代码重新创建了这个问题,如下所示:

import express from 'express';
import socketio from 'socket.io';
import http from 'http';

const PORT = process.env.PORT || 8000;

const app = express();
const server = http.createServer(app);
const io = socketio(server);

server.listen(PORT, () => {
    console.log(`Listening on port ${PORT}`);
});

const checkLength = (bar) => {
    if(bar.length > 14){
        throw Error('word is too long!');
    }
    // ...
}

io.on('connection', socket => {
    console.log('new socket connection');

    socket.on('foo', ({bar}) => {
        try{
            checkLength(bar);
        }catch(e){
            socket.emit('error', e.message);
            return;
        }
        console.log('app did not crash!');
    });
}

bar 的长度大于 14 时,应用会崩溃并出现上述相同的错误。

【问题讨论】:

  • 您是否可能缺少关于 .on 事件的 catch 语句? IE。 io.on('connection', socket => {}).catch((err) => {}) ?.您使用的是哪个 websocket 库?
  • @Phobos 我正在使用 socket.io。我没有针对 io.on('connection') 事件的 catch 语句,但是我正在监听的其他事件中的 try-catch 块有效 - 只是不是这个,这很奇怪。
  • @Phobos on 方法本身没有错误处理。如果joinRoom 正在调用不是await-ed 的async 函数,则可能存在问题。如果Promiseasync 函数出错,则不能用常规try-catch 块捕获,除非完成await
  • 我同意@Mike,joinRoom 可能是一个异步函数,因此您需要使用joinRoom().catchError(error => /* handle error here */) 来捕获错误。
  • 非常感谢。虽然,这个问题一直都在我们眼前。我已经添加了我的答案。

标签: javascript node.js typescript websocket


【解决方案1】:

我注意到您尚未初始化您的 PLAYER 变量。

let PLAYER = {};

#编辑 1:

尝试为您的套接字服务器添加一个错误处理程序并记录它以了解导致错误的原因。

socket.on('error', (error) => {
  console.log(error);
});

【讨论】:

  • 我在我的代码中这样做了,但在删除 PLAYER 的类型声明时意外地摆脱了初始化。刚刚在我的帖子中修复了它 - 我的错!
【解决方案2】:

在我的本地计算机上复制服务器后,我意识到您在为 socket.io 保留关键字上调用 emit。当您调用socket.emit('error', e.message) 时,存在预期的侦听器。像这样的:

socket.on('error', err => {
  // An error occurred. 
})

您应该为您的emit 使用不同的短语。我个人在我的套接字服务器上使用oopssocket.emit('oops', {error})。您可以在他们的page 上阅读有关错误处理的更多信息。

补充一点,socket.emit('error') 不会将错误或任何数据传递给客户端,而是由服务器处理,这就是您需要使用不同短语的原因。

【讨论】:

    【解决方案3】:

    你可以使用 Promise,然后你可以从 then() 方法中获益,该方法也返回一个 Promise。它最多需要两个参数:Promise 成功和失败情况的回调函数。

    所以你的代码应该是这样的:

    import express from 'express';
    import socketio from 'socket.io';
    import http from 'http';
    
    const PORT = process.env.PORT || 8000;
    
    const app = express();
    const server = http.createServer(app);
    const io = socketio(server);
    
    server.listen(PORT, () => {
        console.log(`Listening on port ${PORT}`);
    });
    
    const checkLength = (bar) => {
      return new Promise((resolve, reject)=>{
        if(bar.length > 14){
          // throw Error('word is too long!');
          reject('word is too long!')
        } else {
          resolve('app did not crash!')
        }
      });  
    }
    
    io.on('connection', socket => {
      console.log('new socket connection');
      socket.on('foo', ({bar}) => {
        checkLength(bar).then((result) => {
            console.log('app did not crash!');
        }).catch(err => {
          console.log("app did crash with this error:", err);
        });
      });
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-31
      • 1970-01-01
      • 1970-01-01
      • 2020-10-22
      • 2017-09-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多