【问题标题】:Multiple axios get requests in socket.io. Sending two events via `socket.emit` at the same time多个 axios 在 socket.io 中获取请求。同时通过 `socket.emit` 发送两个事件
【发布时间】:2019-07-12 03:23:44
【问题描述】:

我正在尝试在 socket.io 中创建多个 axios 请求。如果我同时有:

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 工作。

如何将其结合起来,使其同时发挥作用?

我可以创建两个服务器吗?一个支持第一个组件和请求获取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 
        }));
    }
}

【问题讨论】:

  • 你的处理函数是什么?你是如何处理这两个事件的?您可以在问题中发布吗?
  • @AritraChakraborty 它在客户端是如何运作的?这就是你的意思?
  • 是的。客户端代码。
  • @AritraChakraborty 我更新了我的问题
  • 我认为您发送到不正确的套接字。你能用io.emit 代替socket.emit 吗?io 是你的socket-io 实例。

标签: javascript node.js reactjs socket.io axios


【解决方案1】:

我一直在研究你的问题,这是我的结论:

事件发射工作得很好

我以这种方式重建了您的后端:

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

组件 A:

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 中的异步调用后状态如何变化)。 因此,唯一可能会干扰的是您在 componentDidMount 中进行的 axios 调用,因为在这两个组件中,io.listen 没有设置为 componentDidMount 它应该是怎样的(我假设你有理由这样做),所以两个组件都必须在事件发出之前更新状态,否则如果属性dataabcd 没有及时更新,则将在后端发出数据后调用事件侦听器。如果你省略Emit2Emit1,你的说法会很好。但是,省略Emit1 怎么样? Emit2 也可以吗?看起来像一个竞争条件,componentAcomponentDidMount 中的某些内容阻止了 componentB 更新,反之亦然

可能的解决方案

将 io 的侦听器放在两个组件中的 componentDidMount 中,以确定是否是这种情况。老实说,我想不出任何其他可能导致这种情况的问题。

【讨论】:

  • 我已经尝试过放入componentDidMount()。但是在setState ({}) 的组件“A”中,我在加载组件之前设置了“activeTab:res.data [0] .id”活动选项卡。当我点击'tab 3'时,它会自动移动到tab 1 ->`activeTab: res.data [0] .id`
  • 我没有解决。我删除了 activeTab:res.data[0].id。来自 this.setState。现在我有一个问题如何在组件 didmount 中设置 activeTab
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-09
  • 2020-08-06
  • 1970-01-01
  • 2018-06-23
  • 2012-03-30
  • 2019-11-06
相关资源
最近更新 更多