Множественный ответ Socket.io вместо одного - PullRequest
1 голос
/ 05 октября 2019

У меня проблема с socket.io и узлом js.

Контекст

У меня есть два сервера, один из которых обрабатывает тяжелые задания, идругой отвечает клиентам. Основной случай следующий:

  1. Данные запроса клиента
  2. «Средний сервер» проверяет, есть ли у меня эти данные в базе данных. Если нет, отправьте запрос второму серверу
  3. Второй сервер выполняет исследование.
  4. Как только он будет завершен, второй сервер отправит данные на "средний сервер"
  5. Средний сервер наконец передает данные клиенту (и сохраняет их для будущих клиентских запросов)

Вот пример кода

Клиент

<script type="text/javascript"/>
    var socket = io('https://localhost:9091', {'forceNew': true);
    // send a request to the mid server
    socket.emit('request', data);

    socket.on('response', async (response) => {
        // when the mid server responds, the response is printed
        $('#container').append(response);
    });
</script>

Средний сервер

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

// in order to use this server as a Socket.io client
const secondServer = require('socket.io-client').connect('http://localhost:9092');

app.set('view engine', 'ejs');

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

io.on('connection', async (socket) => {

    console.log('User connected');

    // On client request
    socket.on('request', async (data) => {

        console.log('Requesting from ' + socket.id);

        // The same request is transmited to the second server
        secondServer.emit('request', data);
    });

    // Once the second server has finished his job
    secondServer.on('response', async (data) => {

        console.log('Responding for ' + socket.id);

        // I send the data back to the client
        socket.emit('response', data);
    });

    socket.on('disconnect', () => {
        socket.disconnect();
    });
});

// port is 9091
http.listen(port, () => {
    console.log('Server listening on port ' + port);
});

Второй сервер

const io = require("socket.io").listen(9092);

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

    socket.on('request', async () => {
        // await in order to wait the heavyJob to be done before sending the response
        var data = await heavyJob()

        // Send back the data to the mid server
        socket.emit('response', data);

    });
});

Проблема

Проблема, с которой я сталкиваюсь, заключается в том, что, если я обновлю страницу клиента, промежуточный сервер отправит дважды данные, один раз на старый сокет и один раз на новый, так:

console output

Я также попытался ответить клиенту с помощью socket.emit('response', data) на стороне сервера и socket.on('response', (data) => {}) на стороне клиента вместо использования функции callback. Это ничего не меняет.

Я что-то неправильно понимаю?

Спасибо за вашу помощь

Редактировать

Это не такЭто происходит только тогда, когда клиент обновляет свою страницу. Это происходит, когда два разных клиента отправляют запрос одновременно. Сервер отвечает четыре раза, два раза для каждого клиента.

console output

1 Ответ

1 голос
/ 05 октября 2019

Вы правы, Нико, я не узнал, что обратный вызов не может быть достигнут. Это была моя ошибка.

В соответствии с вашим отредактированным кодом вы можете извлечь "secondServer.on ('response' .." from "io.on ('connection'" 'Обратный вызов s.

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

Mid Server

io.on('connection', async (socket) => {

    console.log('User connected');

    // On client request
    socket.on('request', async (data) => {

        console.log('Requesting from ' + socket.id);

        // The same request is transmited to the second server
        // give data and socket.id to secondServer.
        secondServer.emit('request', {data:data, id:socket.id});
    });

    // Once the second server has finished his job
    socket.on('disconnect', () => {
        socket.disconnect();
    });
});

secondServer.on('response', async (reply) => {
    const {id, data} = reply;
    console.log('Responding for ' + id);
    // I send the data back to the client
    io.to(id).emit('response', data);
});

Второй сервер

const io = require("socket.io").listen(9092);

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

    socket.on('request', async (req) => {
        // await in order to wait the heavyJob to be done before sending the response
        const {id} = req; 
        var data = await heavyJob();
        const reply = { id, data };
        // Send back the data to the mid server
        socket.emit('response', reply);

    });
});

Я думаю, вам нужно вытащить код "secondServer.on ('response' ..") из обратного вызова "socket.on ('request', ...".

io.on('connection', async (socket) => {

    console.log('User connected');
    // On client request
    socket.on('request', async (data, callback) => {

        console.log('Requesting from ' + socket.id);
        // The same request is transmited to the second server
        secondServer.emit('request', data);
    });
    secondServer.on('response', async (data) => {
            console.log('Responding for ' + socket.id);
            callback(data.images);
    });  
});
...