【问题标题】:socket.io events inside expressexpress 内的 socket.io 事件
【发布时间】:2016-10-27 07:25:33
【问题描述】:

为了简化,我实际上有主页(/)和搜索页面(/search),在搜索页面中,我想使用socket.io向用户发送信息,因为我只想发送信息到一个套接字,我需要 io.on('connection' ...).

这是我的代码,无法正常工作。当我第一次进入 /search 时,一切正常,但是当我重新加载时,控制台会记录两次“消息 #2”。

控制台

First time
----------
Message #1
Message #2

Second time
----------
Message #1
Message #2

Message #1
Message #2
Message #2

server.js

var express = require('express');  
var app = express();  
var server = require('http').createServer(app);
var io = require('socket.io')(server);

app.set('view engine', 'ejs');
app.use( express.static( "public" ) );

app.get('/', function(req, res) {
    res.render('index');
});

app.get('/search', function(req, res) {
    res.render('search');

    console.log('Message #1');

    io.on('connection', function(socket) {

    console.log('Message #2'); // Here's the problem

        getSearch('something', function (err, data) {
            if (err) {
                console.log("ERROR : ", err);
            } else {
                socket.emit('fetchSearch', data);
            }
        });

    });

});

server.listen('3000');

搜索

<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="../favicon.png" rel="shortcut icon" type="image/x-icon">

    <title>Title</title>

    <script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
</head>
<body>
<script>
    var socket = io();

    socket.on('fetchSearch', function(rows){
        // Rows is an array
    });
</script>
</body>
</html>

关于正在发生的事情或如何解决它的任何想法?

【问题讨论】:

  • 好吧,让我们看看。事件处理程序运行一次,然后两次,然后是三次,所以......您必须多次将事件处理程序绑定到事件。您的代码似乎证实,每次调用 /search 都会向连接事件添加另一个处理程序。
  • 你的意思是如果你导航到/search,你会看到Message #1Message #2,但是如果你刷新你只会看到Message #2
  • 如何更改它才能正常工作? PD:我编辑了控制台日志
  • 请发布“搜索”视图的前端代码。
  • 你真的第二次收到 5 条消息?

标签: javascript node.js express socket.io


【解决方案1】:

您的模型有点倒退。有一台服务器和可能有许多客户端。因此,服务器需要在启动时为传入的 socket.io 连接设置一次监听器。

然后,您将客户端代码放置在要创建与服务器的 socket.io 连接的任何 HTML 页面中。因此,HTML 页面中的代码决定了哪些页面创建了与服务器的 socket.io 连接,哪些没有。这些页面还决定从服务器监听哪些 socket.io 消息。

稍后,当您想向特定客户端或所有客户端发送某些特定信息时,您的服务器可以使用.emit() 向一个或多个当前连接的客户端发送特定消息。

当前已连接并正在侦听该消息以及该消息发送给的客户端随后将收到该消息并可以对其采取行动。


因此,在您的特定服务器代码中,移动:

io.on('connection', function(socket) {...}

在任何事件处理程序之外编写代码并在服务器初始化时运行它。您永远不想多次运行它(这就是您正在做的事情,因为您将它放在 /search 事件处理程序中,因此每次/search 页面出现时,它都会为 connection 事件添加一个新的事件侦听器命中。这很糟糕,并且会创建重复的事件处理程序。在服务器初始化时运行一次。

然后,确保/search 页面包含用于创建与服务器的socket.io 连接的Javascript。

然后,您可以随时从您的服务器向任何当前加载了/search 页面的浏览器发送消息。


然后,在服务器上的/search 路由处理程序中,您必须准确地决定您要做什么。您无法从/search 的路由处理程序将数据发送到/search 页面的socket.io 连接,因为浏览器甚至还没有接收或加载/search 页面,所以还没有页面(以及相应的socket.io 连接)发送到。如果您只是想用数据填充来自/search 的响应,那么您应该将该数据放入http 响应本身,而不是使用socket.io。 socket.io 应该用于在浏览器加载页面之后以及很久以来的 http 响应之后对页面进行进一步更新。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-07
    • 2022-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多