Node.js, как использовать socket.io в экспресс-маршруте - PullRequest
7 голосов
/ 01 июня 2019

В одном из моих скриптов node.js я пытаюсь использовать socket.io в экспресс-маршруте. Я нашел много похожих вопросов и попытался реализовать решение, как предлагалось, но ничего не получилось. Может быть из-за моего непонимания экспресс маршрутов. Я перешел по ссылкам ниже,

Как использовать socket.io в экспресс-маршрутах с node.js

Использование socket.io в маршрутах expressjs вместо основного файла server.js

Это мой app.js

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

const PORT = 3000;
server.listen(PORT);
console.log('Server is running');
var api = require('./routes/api');

//app.use('/api', api);
app.use('/api', (req, res) => {
res.sendFile(__dirname + '/api.html');
});

app.get('/', (req, res) => {
   res.send("this is home location");
});

И файл маршрута api.js в папке ./routes

var express = require('express');
var router = express.Router();
var fs = require("fs");
var bodyParser = require('body-parser');

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

console.log("inside api route");

router.get('/', function(req, res, next) {
console.log("api route called");

const connections = [];
var jsonobj = [{name:"john",score:345},{name:"paul",score:678}]

io.sockets.on('connection',(socket) => {
    connections.push(socket);
    console.log(' %s sockets is connected', connections.length); // this is not printing

    socket.on('disconnect', () => {
       connections.splice(connections.indexOf(socket), 1);
    });

    socket.emit('server message', jsonobj);

 }); 
    //res.send(jsonobj) 
});

module.exports = router;

Socket.emit не показывает данные на html-странице, которую я отображаю при использовании маршрута. Мой HTML-код,

// api.html

<!DOCTYPE html>
<html lang="en">

<body>
   <div class="container">
      <h1 class="jumbotron">
         Node js Socket io with  socket route example
      </h1>
      <div class="results">results</div>      
   </div>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
   <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>
   <script>
    jQuery(document).ready(function() {
       var socket = io.connect();
       var jsondata = "";

       socket.on('server message', function(data){
         console.log('got data from server',data)
         jsondata = JSON.stringify(data);
         //console.log('jsondata',jsondata)
         $('.results').html(jsondata);
       });
    });   
 </script>
</body>
</html>

Пожалуйста, предложите, что я должен получить данные сокета маршрута на html-странице. Спасибо

Ответы [ 4 ]

4 голосов
/ 01 июня 2019

На первый взгляд кажется, что вы деласкалировали префикс URL дважды. Один раз в app.js и снова в api.js.

Попробуйте localhost: порт / API / API

Если это так, измените

router.get('/api', function(req, res, next){

до

router.get('/', function(req, res, next){

Это позволит вам нажать localhost: port / api и получить доступ к вашей конечной точке.

0 голосов
/ 09 июня 2019

Вы пытались создать и запустить серверы из двух разных мест в одном проекте, что неудобно.Вам просто нужна очистка, вот и все.

app.js

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


// Listen to sockets here instead of listening in routes/api.js
const connections = [];
var jsonobj = [{name:"john",score:345},{name:"paul",score:678}]

io.sockets.on('connection',(socket) => {
  connections.push(socket);
  console.log(' %s sockets is connected', connections.length); // this is not printing

  socket.on('disconnect', () => {
     connections.splice(connections.indexOf(socket), 1);
  });

  socket.emit('server message', jsonobj);

});

const PORT = 3000;
server.listen(PORT);
console.log('Server is running');
var api = require('./routes/api');

//app.use('/api', api);
app.use('/api', (req, res) => {
res.sendFile(__dirname + '/api.html');
});

app.get('/', (req, res) => {
   res.send("this is home location");
});

routs / api.js

var express = require('express');
var router = express.Router();
var fs = require("fs");
var bodyParser = require('body-parser');

// Comment these out
// const app = express();
// const server = require('http').createServer(app);
// const io = require('socket.io').listen(server);

console.log("inside api route");

router.get('/', function(req, res, next) {
console.log("api route called");

  // Comment these out

  // const connections = [];
  // var jsonobj = [{name:"john",score:345},{name:"paul",score:678}]

  // io.sockets.on('connection',(socket) => {
  //     connections.push(socket);
  //     console.log(' %s sockets is connected', connections.length); // this is not printing

  //     socket.on('disconnect', () => {
  //        connections.splice(connections.indexOf(socket), 1);
  //     });

  //     socket.emit('server message', jsonobj);

  //  }); 
      //res.send(jsonobj) 
});

module.exports = router;

Оставьте свой api.html как есть.Надеюсь, это поможет.

0 голосов
/ 07 июня 2019

Я только начинаю понимать это сам, но я думаю, что вы находитесь близко.

В вашем app.js добавьте в конец файла:

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

const PORT = 3000;
server.listen(PORT);
console.log('Server is running');
var api = require('./routes/api');

//app.use('/api', api);
app.use('/api', (req, res) => {
res.sendFile(__dirname + '/api.html');
});

app.get('/', (req, res) => {
   res.send("this is home location");
});

app.set("socketio", io);    // <== this line

Это хранит переменную «io» в «socketio».Который вы можете получить в любом из ваших других файлов ".js".

var express = require('express');
var router = express.Router();
var fs = require("fs");
var bodyParser = require('body-parser');

const app = express();
const server = require('http').createServer(app);
//const io = require('socket.io').listen(server); // <== change this
const io = app.get("socketio"); // <== to this

console.log("inside api route");

router.get('/', function(req, res, next) {
console.log("api route called");

const connections = [];
var jsonobj = [{name:"john",score:345},{name:"paul",score:678}]

io.sockets.on('connection',(socket) => {
    connections.push(socket);
    console.log(' %s sockets is connected', connections.length); // this is not printing

    socket.on('disconnect', () => {
       connections.splice(connections.indexOf(socket), 1);
    });

    socket.emit('server message', jsonobj);

 }); 
    //res.send(jsonobj) 
});

module.exports = router;

И вы должны делать это с любыми другими переменными, которые требуются в других файлах ".js".

Также обратите внимание, что в ваших файлах вы снова настраиваете переменные.Лучше сделать то же, что я показал вам с помощью «io».Единственная переменная в других файлах, которые я настраиваю, - это само приложение.

Надеюсь, это поможет ...

0 голосов
/ 04 июня 2019

Хорошо, давайте попробуем понять, зачем вам сначала отправлять данные через сокет внутри маршрута.Веб-сокеты предназначены для асинхронной отправки данных без необходимости выполнения запроса клиентом.Если клиент уже отправляет запрос HTTP, вы можете просто отправить данные в ответ HTTP.

Теперь, сказав, что есть некоторые случаи использования, когда вы должны отправлять данные на какой-либо канал WebSocket, основываясь на действиях запросов ДРУГОГО пользователя.Если это так, есть несколько способов сделать это.Один простой способ - использовать событийную архитектуру .

Попробуйте что-то вроде этого ... найдите мои комментарии ниже:

const express = require('express');
const router = express.Router();
const fs = require("fs");
const bodyParser = require('body-parser');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io').listen(server);

// move the socket connection outside of the route controller
// you must register the event listeners before anything else
const connections = [];

io.sockets.on('connection', (socket) => {
    connections.push(socket);
    console.log(' %s sockets is connected', connections.length); // this is not printing

    socket.on('disconnect', () => {
        connections.splice(connections.indexOf(socket), 1);
    });
});


// Event emitter for sending and receving custom events
const EventEmitter = require('events').EventEmitter;
const myEmitter = new EventEmitter();

myEmitter.on('my-event', function (jsonobj) {
    // do something here like broadcasting data to everyone
    // or you can check the connection with some logic and 
    // only send to relevant user
    connections.forEach(function(socket) {
        socket.emit('server message', jsonobj);
    });
});

router.get('/some-route', function (req, res, next) {  
    const jsonobj = [{ name: "john", score: 345 }, { name: "paul", score: 678 }]

    // emit your custom event with custom data
    myEmitter.emit('my-event', jsonobj);

    // send the response to avoid connection timeout
    res.send({ok: true});
});

module.exports = router;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...