Несколько axios получают запросы в socket.io.Отправка двух событий через `socket.emit` одновременно - PullRequest
0 голосов
/ 08 июля 2019

Я пытаюсь создать несколько запросов axios в socket.io.Если у меня одновременно:

socket.emit ("Emit1", req1.data); socket.emit ("Emit2", req2.data);

socket.emit("Emit2", req2.data); работает.socket.emit ("Emit1", req1.data); не работает.

При удалении socket.emit("Emit2", req2.data); -> emit1 работает.

Как его объединить, чтобы он работал одновременно?

Могу ли я создать два сервера.Один поддерживает первый компонент и запрос get url1, а второй сервер поддерживает запрос url2?

const Emit = async socket => {
    try{
      const [req1, req2] = await Promise.all([
        axios.get(url1, {
          headers: {

          }
        }),
        axios.get(url2, {
          headers: {
            'Authorization': `Bearer ${token}`
          }
        })
      ]);

      socket.emit("Emit1", req1.data);
      socket.emit("Emit2", req2.data); 
    }

    catch(error){
        console.log(error)
    }
};

Клиент

Первый компонент:

import socketIOClient from "socket.io-client";

componentDidMount() {
    axios.get
        axios({
            url,
            method: "GET",
            headers: {
                'Authorization': `Bearer ${token}`
            }
        })
        .then(res => {
            this.setState({
                scores: res.data,
                activeTab: res.data[0].id
            });
        })
        .catch(error => {
            console.log(error);
        })      
}


componentDidUpdate(prevProps, prevState) {
    const endpoint = 'http://127.0.0.1:3000'; 

    if (prevState.scores !== this.state.scores) {
        const socket = socketIOClient(endpoint);
        socket.on("Emit1", data => this.setState({ 
            scores: data 
        }));
    }
}

Второй компонент:

import socketIOClient from "socket.io-client";

componentDidMount() {
    axios.get
        axios({
            url,
            method: "GET",
            headers: {
                'Authorization': `Bearer ${token}`
            }
        })
        .then(res => {
            this.setState({
                abcd: res.data
            });
        })
        .catch(error => {
            console.log(error);
        })      
}


componentDidUpdate(prevProps, prevState) {
    const endpoint = 'http://127.0.0.1:3000'; 

    if (prevState.abcd !== this.state.abcd) {
        const socket = socketIOClient(endpoint);
        socket.on("Emit2", data => this.setState({ 
            abcd: data 
        }));
    }
}

1 Ответ

1 голос
/ 11 июля 2019

Я уже некоторое время работаю над вашим вопросом, и вот мои выводы:

Эмиссия событий работает просто отлично

Я восстановил ваш бэкэнд следующим образом:

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

app.use(express.json())

app.get('/emit', async({ res }) => {
    const [data1, data2] = await Promise.all([fakeApiCall(1), fakeApiCall(2)])
    io.emit('Emit1',data1)
    io.emit('Emit2',data2)
    res.status(200).json('emitted')
})

const fakeApiCall = id =>{
    return new Promise((resolve, reject) =>{
        setTimeout(() => resolve(`data${id}`), 3000)
    })
}

http.listen(port, () => console.log('listening on port ' + port))

По сути, это именно то, что вы делаете, и работает отлично, оба события выдают после того, как Promise.all выполнит все обещания.

Настройка внешнего интерфейса работает

После этого я сделал версию вашего интерфейса:

App.js:

import React from 'react'
import ComponentA from './ComponentA'
import ComponentB from './ComponentB'

const App = () => {
    return (
        <>
            <ComponentA />
            <ComponentB />
        </>
    )
}


export default App

Компонент А:

import React from 'react'
import socketIOClient from 'socket.io-client'

class ComponentA extends React.Component {
    state = {
        data: null
    }

    componentDidMount(){
        setTimeout(() => this.setState({data: 'bla'}), 2000)
    }


    componentDidUpdate(prevProps, prevState) {
        const endpoint = 'http://127.0.0.1:3003';

        if (prevState.data !== this.state.data) {
            const socket = socketIOClient(endpoint);
            socket.on("Emit1", data => this.setState({ data }))
        }
    }

    render() {
        const { data } = this.state
        return (
            <div>
                {data}
            </div>
        )
    }
}
export default ComponentA

Компонент B:

import React from 'react'
import socketIOClient from 'socket.io-client'

class ComponentB extends React.Component {
    state = {
        data: null
    }

    componentDidMount(){
        setTimeout(() => this.setState({data: 'bla'}), 2000)
    }


    componentDidUpdate(prevProps, prevState) {
        const endpoint = 'http://127.0.0.1:3003';

        if (prevState.data !== this.state.data) {
            const socket = socketIOClient(endpoint);
            socket.on("Emit2", data => this.setState({ data }))
        }
    }

    render() {
        const { data } = this.state
        return (
            <div>
                {data}
            </div>
        )
    }
}
export default ComponentB

И что удивительно ... Работает просто отлично! Итак, в чем здесь разница? Все выглядит одинаково (как генерируются события, как слушатель вставляется только в componentDidUpdate, как изменяется состояние после асинхронного вызова в componentDidMount). Таким образом, единственное, что может помешать, это вызов axios, который вы делаете внутри componentDidMount, потому что в обоих компонентах io.listen не установлен на componentDidMount, как это должно быть (я полагаю, у вас есть причины для этого), поэтому оба компонента ДОЛЖНЫ обновить состояние до того, как событие будет выпущено, в противном случае, если свойства data или abcd не будут обновлены вовремя, прослушиватель событий будет вызван после того, как бэкэнд испустит данные. И ваше утверждение о том, что если вы пропустите Emit2 Emit1, будет работать нормально. Но как насчет опустить Emit1? Emit2 тоже будет работать? Похоже на состояние гонки, что-то в componentA componentDidMount мешает componentB обновлять или наоборот

Возможное решение

Поместите слушателей io в componentDidMount в обоих компонентах, чтобы определить, так ли это. Потому что, честно говоря, я не мог думать ни о какой другой проблеме, которая может быть причиной этого.

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