Forward request to ws client and wait for response Express

前端 未结 3 1882
抹茶落季
抹茶落季 2020-12-22 11:41

I\'m trying to build an endpoint that will receive a request, emit the request data to a WebSocket client, wait for an event, then send back the response using express + soc

相关标签:
3条回答
  • 2020-12-22 12:14

    Please note that:

    socket.on('res', function (data) {
        res.status(200).json(data);
    });
    

    Is being called each time a socket is sending a response, thus showing the above error. You should unbind the listener inside the callback function.

    0 讨论(0)
  • 2020-12-22 12:14

    You're trying to do two different async tasks for the same data.

    First, take your socket.on('res'...) out of the app.get().

    Send back res.status(200) immediately with express to say you received the request and it is processing. Then send the socket message to the client using socket.io when it's complete. You'll want to save the connected users socket client ID and use io.to(socketId).emit(...data...) to do this

    the other option is what I always do (assuming it's not a crazy large payload of data you're sending) Just use socket.io for the whole process.


    client

    function makeRequest () {
        socket.on('data-complete--error', function ( error ) {
            // ... message to user :(
            // also remove these handlers when finished
            socket.off('data-complete--error');
            socket.off('data-complete--success');
        });
        socket.on('data-complete--success', function ( data ) {
            // ... message to user :)
            // ... handle data
            // also remove these handlers when finished
            socket.off('data-complete--error');
            socket.off('data-complete--success');
        });
        socket.emit('request-data');
    }
    
    makeRequest();
    

    server

    move your stuff out and handle without using express at all

    0 讨论(0)
  • 2020-12-22 12:15

    Keep an array of express responses and set an id to each request. So it can be used later and delete if needed.

    var app = require('express')();
    var http = require('http').Server(app);
    var io = require('socket.io')(http);
    var timeout = require('connect-timeout');
    var uuid = require('uuidv4');
    var _ = require('lodash');
    
    app.use(timeout('10s'));
    
    app.get('/', (req, res) => {
        res.sendFile(__dirname + '/index.html');
    });
    
    let responses = []
    
    io.on('connection', (socket) => {
        socket.on('res', (e) => {
            var obj = _.find(responses, r => r.id === e.id);
            obj.res.send(e)
            _.remove(responses, r => r.id === e.id);
        })
    })
    
    app.get('/endpoint', (req, res) => {
        const id = uuid()
        io.emit('req', { id, ip: req.ip, header: req.headers, method: req.method });
        responses.push({ id, res })
    });
    
    http.listen(3000);
    
    0 讨论(0)
提交回复
热议问题