【问题标题】:Is there a way to put socket.io events into functions?有没有办法将 socket.io 事件放入函数中?
【发布时间】:2022-01-03 00:32:04
【问题描述】:

我想将 socket.io 事件封装到函数中,使其对我的项目更具可读性,这是一个示例。我想把这个:

io.on('connection', (socket) =>{
            //code
});

变成这样:

function isThereANewConnection() {
 io.on('connection', (socket) =>{
        //..return true?
 });
}

function update() {
   if(isThereANewConnection()) {
    //do something with the socket data..
  }
}

我似乎无法弄清楚如何实现这一点,因为我无法从函数中返回某些内容。有谁知道怎么做?

【问题讨论】:

  • 这似乎是XY problem。这不是回调通常的工作方式。 “如果有新连接”的想法不是您在同步流中的条件中编码的东西,它是在回调触发时隐含地为真的东西。换句话说,只需将您的逻辑放在回调中,不需要if。如果update 必须知道回调中的信息,则回调可能会改变update 函数在运行时可以读取的共享状态,但是如果没有更多上下文,很难推荐任何具体的内容。
  • 您不需要将它们放在更新函数中,因为它们已经是事件侦听器。他们自己处理“更新”过程
  • 您要在这里解决的真正问题是什么。您的服务器不应该想要阻止下一个连接。它应该为任何新连接到达时注册一个事件处理程序。如果您向我们展示您认为自己想要这样做的原因,那么我们可以更好地帮助您解决您的实际问题(可能不会按照您目前的方向发展,因为这不是您进行多用户事件驱动编程的方式)。
  • @jfriend00 是的,问题是我正在尝试制作一个面向对象的多人游戏,游戏本身就像玩家和输入类都是面向对象的。我正在考虑以这样一种方式设计我的服务器类,它也是 OOP,并在该特定类的更新方法中编写所有逻辑,就像游戏一样。但我认为我应该以不同的方式处理服务器架构?
  • 将代码包装成函数本身并不是目的。一个函数至少必须接受并返回一个值,否则你只是在滥用它的接口。使用可组合的事件流(async/push)从 socket.io 事件中抽象出来更有意义。您可以将其实现为 Observable 或无状态的惰性 Promise(在 FP 术语中称为 Task)。

标签: javascript node.js oop socket.io functional-programming


【解决方案1】:

您还没有真正解释通过将“事件放入函数”来实现的目标,因此很难准确地知道您希望它是什么样子。

从本质上讲,nodejs 是一个事件驱动的环境。因此,您注册事件侦听器并在发生事件时呼叫您。这就是socket.io连接事件的结构。

如果您不希望所有内容都像这样内联:

io.on('connection', (socket) =>{
            //code
});

您可以将事件侦听器回调放入函数本身,例如:

io.on('connection', onConnection);

然后,在其他地方(在同一模块中或导入到此模块中),您将定义 onConnection 函数。

function onConnection(socket) {
    // put your code here to handle incoming socket.io connections
    socket.on('someMsg', someData => {
        // handle incoming message here
    });
}

注意:内联回调函数(您似乎要求避免的类型)在 nodejs 编程中非常常见。使用它们的原因之一是,当它们内联时,它们可以使用父作用域中的所有变量(不必将它们全部作为参数传递),有时这非常有用。所以,它可能是一种你会觉得有用而不是避免的风格。

【讨论】:

  • 我正在制作一个面向对象的乘法游戏,游戏本身是 OOP 结构,就像它具有针对特定类逻辑的更新方法一样,我正在考虑以这样的方式构建我的服务器类可以理解和 OOP,但我认为我应该为此采取不同的方法,感谢您的明确解释:)
  • @ShaileshChotoe - 您的问题非常不清楚,并且缺少您想要做什么的详细信息。如果您在问题中添加更多内容来解释您正在尝试做的事情,我会尽力帮助您。如果你想要一个 OO 设计,那么展示你计划拥有的类并描述你希望 socket.io 事件如何适应它。就您现在的问题而言,它没有描述任何内容。请编辑您的问题以澄清。
【解决方案2】:

我认为这不会以对您来说更易读和更有用的方式来构建您的代码。但如果你确实想要这个,你可以使用async/await

async function getNewConnection() {
  return await new Promise((resolve, reject) => {
    io.on('connection', resolve);
  });
}

然后在你的其他代码中:

const socket = await getNewConnection();

确实,对于这个连接处理程序,您应该坚持使用回调模式。它使您的事情变得简单。在连接建立时运行更新,而不是相反。

【讨论】:

  • 我想你是想写return new Promise(...)?但这还有另一个问题是io.on("connection", cb) 将在有新的套接字连接时触发其回调,因此它可以执行多次。然而,由于一个 Promise 只能被解析一次,所以只有第一个套接字连接会从你的 Promise 中获得,而所有其他套接字连接都不会做任何事情,因为 Promise 已经解析了。
  • @NickParsons 是的,感谢您发现丢失的return。是的,完全同意一次性解决的承诺,这是我认为这不是问题的正确结构的原因之一。但是,我想我会提到这个 async/await 的东西,因为这个人显然正在学习,并且有点触及这个概念。
  • 既然你有了return,为什么return await ... 中有await?实际上,您可以删除async 关键字和await。我试图教人们(尤其是初学者)远离return await,因为这让他们认为函数正在返回一个值,而实际上它不是——它正在返回承诺,而await 没有任何价值。
  • @jfriend00 纯代码风格。通常在这样的函数中,我会有几个等待,我喜欢保持一致而不是表明我正在返回承诺。
【解决方案3】:

更新:我已经找到了这个的 OOP 解决方案(它不是最好的):

class ConnectionHandler {

init() {
  this.listenForConnections();
}

listenForConnections() {
 io.on('connection', (socket) =>{
        //do stuff
        this.newConnection = true;
        this.update();
 });
}

// the update method contains all the logical decisions of a class
update() {
   if(this.isThereANewConnection()) {
    //add connection to list.. or handle the rest of the logic
  }
  //render screen
}

isThereANewConnection() {
   if(this.newConnection) {
    this.newConnection = false;
    return true;
  }
 return false;
}

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-12
    • 2021-02-04
    • 1970-01-01
    • 2020-11-19
    • 1970-01-01
    • 2023-01-26
    • 2022-01-25
    • 1970-01-01
    相关资源
    最近更新 更多