socket.on 事件被多次触发

2023-12-08

var express = require('express');
var app = express();
var server = app.listen(3000);
var replyFromBot;
app.use(express.static('public'));
var socket = require('socket.io');
var io = socket(server);
io.sockets.on('connection' , newConnection);

function newConnection(socket) {
   console.log(socket.id);
   listen = true;
   socket.on('Quest' ,reply);
   function reply(data) {
     replyFromBot = bot.reply("local-user", data);
     console.log(socket.id+ " "+replyFromBot);
     socket.emit('Ans' , replyFromBot);
  }
}

我使用node.js socket.io和express创建了一个基于服务器的聊天机器人应用程序,但问题是当我第一次调用socket.on时,它会执行一次,第二次它会执行两次,第三次会执行三次,所以我已经通过在我的客户端上设置一个标志来解决这个问题,以便它只显示一次。我只是想知道我的代码在逻辑上是否正确我的意思是这是一个好的代码吗?因为如果客户第 10 次问问题,听众数组将有 10+9+8....+1 个听众,它会根据客户提出的问题数量继续增加。这不好

我尝试使用removeListener,它只删除一次侦听器,并且不会第二次回调。你们有什么推荐?我应该这样做还是有其他方法可以在调用 socket.on 时添加侦听器并在执行时删除它并在下次调用时再次添加侦听器

谢谢。

客户端代码:

function reply() {
  socket.emit('Quest' , Quest);
  flag = true;
  audio.play();
  socket.on('Ans', function(replyFromBot) {
  if(flag) {
    console.log("hi");
    var para = document.createElement("p2");
    x = document.getElementById("MiddleBox");
    para.appendChild(document.createTextNode(replyFromBot));
    x.appendChild(para);
    x.scrollTop = x.scrollHeight;
    flag = false;
  }
 });
}

该问题是由您的客户端代码引起的。每次您致电reply()您在客户端中设置了一个额外的函数socket.on('Ans', ...)事件处理程序这意味着它们会累积。你可以将其更改为socket.once()每次获得后它都会自行删除Ans信息。然后您还可以删除您的flag多变的。

function reply() {
  socket.emit('Quest' , Quest);
  audio.play();
  // change this to .once()
  socket.once('Ans', function(replyFromBot) {
    console.log("hi");
    var para = document.createElement("p2");
    x = document.getElementById("MiddleBox");
    para.appendChild(document.createTextNode(replyFromBot));
    x.appendChild(para);
    x.scrollTop = x.scrollHeight;
  });
}

Socket.io 并不是真正构建为请求/响应系统的,而这正是您尝试使用的系统。实现这一点的更好方法是使用acksocket.io 具有的功能这样您就可以得到直接回复Quest您发送的消息。

您还需要修复共享变量replyFromBot and listen在您的服务器上,因为一旦有多个用户使用您的服务器,这些并发问题就会发生。


更好的解决方案

更好的解决方案是使用acksocket.io 必须能够直接响应您发送的消息。为此,您需要将服务器更改为:

function newConnection(socket) {
    console.log(socket.id);
    socket.on('Quest', function(data, fn) {
      let replyFromBot = bot.reply("local-user", data);
      console.log(socket.id+ " "+replyFromBot);
      // send ack response
      fn(replyFromBot);
    });
}

并且,将您的客户端代码更改为:

function reply() {
    audio.play();
    socket.emit('Quest', Quest, function(replyFromBot) {
        console.log("hi");
        var para = document.createElement("p2");
        x = document.getElementById("MiddleBox");
        para.appendChild(document.createTextNode(replyFromBot));
        x.appendChild(para);
        x.scrollTop = x.scrollHeight;
    });
}

通过这种方式,您可以连接到消息的直接回复,因此它作为请求/响应的工作方式比您以前的方式要好得多。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

socket.on 事件被多次触发 的相关文章

随机推荐

  • 就浮点而言,是否有正确的常量表达式用于其最高有效位?

    问题 给定一个浮点常量表达式 我们可以编写一个宏来计算一个常量表达式 该常量表达式的值是等于尾数最高位的 2 的幂吗 等效地 这只是小于或等于输入幅度的两个的最大幂 出于这个问题的目的 我们可以忽略 接近溢出或接近下溢值 它们可以通过有限多
  • 图表 x 轴编号

    我正在使用 WinForms 图表来可视化一些数据 我想要 x 轴网格线位于我指定的点处 请看下面的例子 public partial class Form1 Form public Form1 InitializeComponent Ad
  • DBMS 或 SVN 中的集中存储库

    我正在努力建立一个集中存储库来存储企业架构师 来自 sparx 系统 生成的工件 供 6 8 人的团队使用 最初考虑托管 PostgreSQL 数据库来集中存储工件 而出现的另一个选择是使用 SVN 查看 EA 文档 没有清楚地了解所考虑的
  • Entity Framework Core / SQLite:Join 后的 GroupJoin“展平”结果

    使用 Entity Framework Core 2 1 和 SQLite 数据库 如果在另一个 Join 之后使用 LINQ GroupJoin 我会得到不同的行为 目前尚不清楚这是一个错误还是我忽略了某些内容 我创建了一个最小的 VS2
  • 以编程方式向 hibernate 提供数据源

    我想知道是否可以以编程方式提供 DataSource 对象来休眠配置 在我们的系统中 我们构建了一个数据源对象 这是一个 Java SE 应用程序 我想从纯 JDBC 代码转移到 hibernate 如果有人知道 JPA 的答案也没关系 您
  • 模拟react元素上的点击事件

    我正在尝试模拟一个 click event on a React元素 但我不明白为什么它不起作用 当我发射时它没有反应event 我想仅使用 JavaScript 发布 Facebook 评论 但我陷入了第一步 执行 click on di
  • 如何在 Chrome 扩展程序中使用 navigator.clipboard.readText()?

    我编写了一个 Firefox 扩展来读取剪贴板 如果它有一些 PEM 证书 它将在新选项卡中打印其详细信息 我正在尝试移植到 Chrome 这是行不通的 我究竟做错了什么 我在manifest json中请求了clipboardRead 并
  • 后台简历上的密码

    我有一个问题是否有合适的方法来处理这种情况 我希望我的应用程序在第一次启动应用程序时立即启动密码活动 或者用户从后台恢复它 例如 用户单击主页按钮并将应用程序移动到后台 然后再次启动它 我知道我可以使用特殊权限并授予对系统任务的访问权限来执
  • Excel 间接计数

    我有一本工作簿 每个月都有不同的工作表 我又做了一张纸 在 A1 中写下了月份 我想同时使用 Counta 用于月份表中的 A A 和间接 但我用公式得到结果 1 请帮忙 COUNTA 间接 工作表名称 A1 A A 我最终也想对 coun
  • 如何两次引用外键表?

    我收到以下错误 u detail u 一个或多个映射器未能初始化 无法继续 与其他映射器的初始化 最初的例外是 可以 无法确定父 子表之间的连接条件 关系 Vote user 有多个外键路径链接 桌子 指定 foreign keys 参数
  • 带阿尔伯斯投影的 D3.js 地图:如何旋转它?

    我正在使用 d3 js 构建菲律宾地图 但由于一个奇怪的原因 该地图看起来像是向左旋转 因此该国看起来并不真实 我尝试修改projection rotate字段 但似乎不是校正线 var width 1060 height 860 var
  • 在 Mac 上,在 Java 中,某些键不会触发 keyPressed 事件

    这是一个非常奇怪的问题 但我只是将一个简单的 keyListener 添加到 JPanel 中 在 keyPressed 和 keyReleased 上打印 通常它工作正常 但在某些键 如 A 上 如果我在释放之前按住 则在释放后没有其他键
  • 从 Tensorflow 中的张量中删除一组张量

    我正在寻找一种简单的方法来从 Tensorflow 中的当前张量中删除一组张量 但我有一个困难的合理解决方案 例如 假设我有以下当前张量 a tf constant 1 0 2 0 3 0 4 0 5 0 6 0 shape 2 3 nam
  • 如何使用 jQuery 更新属性?

    document ready function var hero image new Array hero image 0 new Image hero image 0 src assets images link png hero ima
  • opencv java修改像素值

    我一直在尝试在 opencv java 中转换一些 opencv C 代码 但我似乎无法让像素分割正常工作 我采用了均值偏移分段垫 将其转换为灰度 然后转换为 32F 然后 我将最下采样然后上采样的图像 由灰色均值漂移垫组成 与原始灰色均值
  • Pandas 将每个单元格都是字符串列表的列转换为整数列表

    我有一个包含列的数据框 其中包含数字列表作为字符串 C1 C2 l 1 3 5 9 1 7 1 7 1 6 将其转换为整数列表的最佳方法是什么 C1 C2 l 1 3 5 9 1 7 1 7 1 6 Thanks 你可以试试 df l df
  • 在云端硬盘选择器小部件中仅显示团队云端硬盘

    我正在创建一个应用程序 我需要在其中提供 Drive Picker 小部件 以便用户可以上传一些文件 现在我想限制用户 以便他们只能从 团队驱动器 中选择文件 而不能从其他任何地方选择文件 我尝试过添加方法onPickerInit even
  • 如何使用 xampp 在 ubuntu 中填充 mysql 数据库中的区域表

    我正在尝试根据此文档导入时区 http dev mysql com doc refman 5 7 en mysql tzinfo to sql html 当我尝试通过终端输入第一个命令时 即 mysql tzinfo to sql tz d
  • 如何发布复选框值和选中状态

    i am getting checkbox values checked status checkbox label checkbox courseid from the server using of axios method now i
  • socket.on 事件被多次触发

    var express require express var app express var server app listen 3000 var replyFromBot app use express static public va