简体   繁体   English

发送 socket.io 实例来表达路由

[英]Sending socket.io instance to express route

I am trying to create a nodejs app that will search in various web sites using their API.我正在尝试创建一个 nodejs 应用程序,该应用程序将使用其 API 在各种网站中进行搜索。 The result will be sent to the client as soon as it receive result from those API using socket.io.使用 socket.io 从这些 API 接收结果后,结果将立即发送到客户端。 The front end will then add those result using jQuery.然后前端将使用 jQuery 添加这些结果。

What is the best way to implement this?实现这一点的最佳方法是什么?

So Far I have tried:到目前为止,我已经尝试过:

Sample code 1示例代码 1

At first I created a middleware for express that add the socket to the request like -起初,我为 express 创建了一个中间件,将套接字添加到请求中,例如 -

var socketMiddleWare = function(req, res, next){
  io.on('connection', function(socket){
    console.log(io.engine.clientsCount + " clients connected.");
    req.socket = socket;
    
    socket.on('disconnect', function(){
      console.log(io.engine.clientsCount + " clients after disconnec.");
    });
    
  });
  next();
};

then added this middleware to my route -然后将此中间件添加到我的路线中 -

app.use('/users', socketMiddleWare, users);

It works but the problem is it create multiple event listener each time user refresh the page.它有效,但问题是每次用户刷新页面时它都会创建多个事件侦听器。

Sample code 2示例代码 2

So then I tried (sample code)然后我尝试了(示例代码)

io.on('connection', function(socket){
  console.log("user connected");
  global.socket = socket;
  socket.on('disconnect', function(){
    console.log("disconnect");
  });
  
  socket.on('my message', function(){
    console.log("My message received");
  });
});

and on my test route I did在我的测试路线上我做了

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  if(socket){
    socket.emit('response', 'nothing');
  }
  res.render('index', { title: 'Express' });
});

module.exports = router;

It solved the previous problem of multiple event listener on refresh But most of the time it can not emit the response.它解决了之前刷新时多个事件侦听器的问题,但大多数时候它无法发出响应。 And even it emit my browser can not show the result.即使它发出我的浏览器也无法显示结果。 On client side I did something like this -在客户端我做了这样的事情 -

var socket = io.connect('http://localhost');

socket.on('response', function(data){
    console.log(data);        
    document.getElementById("change").innerHTML += data;
});

I can see the response in browser console but my browser show the change for a few milliseconds before it disappear.我可以在浏览器控制台中看到响应,但我的浏览器在更改消失之前会显示几毫秒的更改。

I think the the main problem is The page loads before establishing socket connection.我认为主要问题是在建立套接字连接之前加载页面。

I am currently learning node.js and socket.io.我目前正在学习 node.js 和 socket.io。 So please help me.所以请帮助我。

Conclusion结论

I do have plan to add social network features like one to one message, live friends feed update on home page etc using socket.io in future.我确实计划在未来使用 socket.io 添加社交网络功能,例如一对一消息、主页上的实时好友动态更新等。 Please let me know if there is any good documentation or open source project that can help me implementing it.请让我知道是否有任何好的文档或开源项目可以帮助我实现它。

I am searching for solution for last couple of days but with no luck so far.我正在寻找过去几天的解决方案,但到目前为止还没有运气。 I am ready to learn any new methodology or fully rewrite my code.我准备学习任何新方法或完全重写我的代码。

TL;DR TL; 博士

When a user client search for item, push contents to the client that requested the content when new data available.当用户客户端搜索项目时,当新数据可用时,将内容推送到请求内容的客户端。 Data is available after processing response from website like " The Movie Database " and " TheTVDB.com " through their API.在处理来自“电影数据库”和“ TheTVDB.com ”等网站的响应后,可以通过它们的 API 获得数据。

You can use the ID of the socket to keep track of which socket to send results to.您可以使用套接字的 ID 来跟踪要将结果发送到哪个套接字。

Client客户

When the user then searches for something the ID is included in the query parameters.当用户随后搜索某些内容时,该 ID 将包含在查询参数中。

<body>
    <form>
        <!-- Disable the search bar until the socket is connected -->
        <input type="search" name="q" placeholder="Search" disabled>
    </form>
    <div id="results"></div>
    <script src="/socket.io/socket.io.js"></script>
    <script>
        var resultsElement = document.querySelector("#results");
        var search = document.querySelector("form [type=search]");
        var socket = io("http://localhost:3000");


        socket.on("connect", function(){
            search.disabled = false;
        });

        socket.on("results", function(results){
            for(var i = 0;i < results.length;i++){
                var result = document.createElement("div");
                result.textContent = results[i];
                resultsElement.appendChild(result);
            }
        });

        document.querySelector("form").addEventListener("submit", function(event){
            fetch("/search?socketID=" + encodeURIComponent(socket.id) + "&q=" + encodeURIComponent(search.value));
            event.preventDefault();
        });
    </script>
</body>

Server服务器

When the server receives the search request it gets the socket using the socket ID sent in the query parameters and starts sending results back to the client.当服务器收到搜索请求时,它使用查询参数中发送的套接字 ID 获取套接字,并开始将结果发送回客户端。

var app = require("http").createServer(handler);
var io = require("socket.io")(app);
var fs = require("fs");
var url = require("url");
app.listen(3000);

function handler(req, res) {
    var query = url.parse(req.url, true).query;
    if(req.url.startsWith("/search")){
        var results = ["things", "stuff", "items"];
        // Server-side IDs have "/#" in front of them
        var socket = io.sockets.connected["/#" + query.socketID];
        if(socket){
            // Get and send "search results"
            var interval = setInterval(function(){
                var popped = results.pop();
                if(popped){
                    socket.emit("results", [query.q + " " + popped]);
                }else{
                    clearInterval(interval);
                }
            }, 1000);
        }
        res.writeHead(204);
        res.end();
    }else{
        fs.readFile(__dirname + "/index.html", function(err, data) {
            res.writeHead(200);
            res.end(data);
        });
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM