【问题标题】:Broadcast GET data from API to clients using socket.io使用 socket.io 从 API 向客户端广播 GET 数据
【发布时间】:2014-05-15 13:13:01
【问题描述】:

我不确定我想要实现的目标是否正确,因为我找不到任何示例。

我有一个显示谷歌地图和多个对象的应用程序。我希望每秒钟或 2 次自动更新对象的位置。

我正在考虑拥有一个带有setInterval() 的 nodejs 服务器,它每 2 秒触发一次,以向不同的服务器执行 API 请求,获取数据响应并将其广播到所有 socket.io 客户端。

这是我目前正在使用的server.js

var express = require('express'),
    server = express(),
    port = 3700,
    host = 'localhost',
    io = require('socket.io').listen(server.listen(port, host));

server
    .get('/', function(req, res){
        res.send('OK');
    });

io.sockets.on('connection', function(socket){
    console.log('connection started');

    // Update the server date every seconds
    setInterval(function(){
        socket.emit('date', {'date': new Date()});
    }, 1000);

    // Update locations every minutes
    setInterval(function(){
        console.log('Client: ' + socket.id);
        io.sockets.emit('update_locations', []);
    }, 1000);
});

io.sockets.on('disconnect', function(socket){
    console.log('Client "' + socket.id + '" disconnected');
});

看看我想在哪里广播update_locations 消息。 我正在调查我应该如何执行对我的 API 的请求?

  • 我做对了吗?
  • 我应该在我的setInterval() 函数中使用http.get() 吗?
  • 我应该使用setInterval()吗?如果没有setInterval(),我将无法做到这一点

欢呼, 马克西姆

【问题讨论】:

    标签: node.js express socket.io


    【解决方案1】:

    我正在详细回答我自己的问题:

    感谢 Lellansin 为我指明了正确的方向:

    这是我的server.js

    var express = require('express'),
        debug = true,
        http = require('http'),
        _ = require('underscore'),
        server = express(),
        port = 3700,
        api_host = 'api.acme.local',
        io = require('socket.io').listen(server.listen(port), {log: debug});
    
    
    console.log('Node server listening on port', port);
    io.set('log level', 1);
    
    server
        .get('/', function(req, res){
            res.send('OK');
        });
    
    var clients = {};
    
    io.sockets.on('connection', function(socket){
        console.log('Client ' + socket.id + ' is connected');
    
        // Add the client to the list of connected clients
        clients[socket.id] = true;
    
        // Broadcast to everyone the list of connected clients
        io.sockets.emit('connected_clients', _.size(clients));
    
        // Send the current positions to the connected client when client is ready
        socket.on('ready', function() {
            getCourses(function(data){
                console.log('Send locations to client ' + socket.id);
                socket.emit('update_locations', data);
            });
        });
    
        // When a client is disconnecting, inform other clients
        socket.on('disconnect', function() {
            delete clients[socket.id];
            console.log('Client "' + socket.id + '" disconnected');
            io.sockets.emit('connected_clients', _.size(clients));
        });
    });
    
    // Update locations every minutes
    setInterval(function()
    {
        // Do nothing if there is no client
        if (_.size(clients) == 0) {
            return;
        }
    
        console.log('Update positions...');
    
        // Get the current courses and broadcast them to all clients
        getCourses(function(data){
            io.sockets.emit('update_locations', data);
        });
    }, 60000); // every minute
    
    // Update the server date every seconds
    setInterval(function(){
        io.sockets.emit('date', {'date': new Date()});
    }, 1000);
    
    
    function getCourses(callback)
    {
        var options = {
            hostname: api_host,
            port: 80,
            path: '/courses',
            method: 'GET'
        };
    
        var req = http.request(options, function(res) {
            //console.log('-----------------------------------------');
            //console.log('STATUS: ' + res.statusCode);
            //console.log('HEADERS: ' + JSON.stringify(res.headers));
            var output = '';
    
            res.setEncoding('utf8');
            res.on('data', function (chunk) {
                output += chunk;
            });
    
            res.on('end', function() {
                var obj = JSON.parse(output);
                if (callback != undefined){
                    callback(obj);
                }
            });
        });
    
        req.on('error', function(e) {
            console.log('problem with request: ' + e.message);
        });
    
        req.end();
    }
    

    如果至少有一个客户端连接,我只会广播数据。我不知道为什么这不是一个好主意,但我会感谢任何批评者。此外,在我看来,如果我在服务器端有多个 API 请求,阅读起来就会开始变得困难。

    【讨论】:

      【解决方案2】:

      io.sockets.emit 意味着向所有人广播,而您的代码意味着当有新连接时,您将获得一个新计时器。如果有 100 个连接,您将新建 100*2 个计时器。我的建议代码如下:

      io.sockets.on('connection', function(socket){
          // signle connection
      
          var timer = setInterval(function(){
              // for signle
              io.sockets.socket(socket.id).emit( ... );
      
              // for all
              // io.sockets.emit( ... );
          }, 1000);
      
          // dont forget clear
          socket.on('disconnect', function() {
              clearInterval(timer)
          });
      });
      
      setInterval(function(){
          // emit for all connection
          io.sockets.emit( ... );
      }, 1000);
      

      希望它有帮助。

      【讨论】:

      • 感谢 Lellansin 的提示,但它并没有回答我所有的问题。
      • @maxwell2022 也许你可以设置一个标志,新的连接进来然后标志++,而标志==也许100,调用API等。
      猜你喜欢
      • 2016-07-21
      • 1970-01-01
      • 2012-01-25
      • 1970-01-01
      • 1970-01-01
      • 2016-12-02
      • 2017-12-21
      • 2020-03-12
      • 2012-07-14
      相关资源
      最近更新 更多