You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何像使用axios一样使用Socket.IO实现请求与错误处理?

解决方案

服务端适配改造

核心逻辑是复用现有REST接口处理函数,无需重写业务代码,仅需要针对Socket.IO请求模拟Express的req、res对象,通过Socket.IO自带的ack回调机制返回响应即可。

完整服务端代码示例

// 引入你原有业务的post相关处理函数
const { postCreate, postList, postUpdate, postDelete } = require('./controllers/post')

io.on('connection', socket => {
    console.log('User is connected on socket');

    // 统一监听post类请求,约定事件名为`post:request`
    socket.on('post:request', async (method, path, data, callback) => {
        // 1. 模拟Express的req对象,结构和原有REST请求的req完全对齐
        const req = {
            body: data,
            user: socket.user, // socket.user为Socket连接鉴权后挂载的用户信息,和原有req.user一致
            query: method === 'GET' ? data : {},
            params: {} // 若路径带参数可自行解析后挂载
        }

        // 2. 模拟Express的res对象,适配原有处理函数的status、json方法
        const res = {
            status(code) {
                this.statusCode = code
                return this
            },
            json(payload) {
                // 调用Socket的ack回调把结果返回给客户端
                callback({
                    status: this.statusCode || 200,
                    data: payload
                })
            }
        }

        // 3. 匹配路由对应处理函数,和你原有REST路由规则对齐
        try {
            if (method === 'POST' && path === '/post/create') return postCreate(req, res)
            if (method === 'GET' && path === '/post/list') return postList(req, res)
            if (method === 'PUT' && path === '/post/update') return postUpdate(req, res)
            if (method === 'DELETE' && path === '/post/delete') return postDelete(req, res)
            // 未匹配到路由返回404
            res.status(404).json({ error: '接口不存在' })
        } catch (err) {
            // 捕获全局异常返回500
            res.status(500).json({ error: '服务端内部错误' })
        }
    })

    socket.on('disconnect', () => console.log('disconnected'))
})

补充鉴权适配

和原有REST接口的token鉴权逻辑对齐即可:

  • 客户端初始化Socket时在auth字段携带token:
const socket = io(服务端地址, {
  auth: { token: localStorage.getItem('token') }
})
  • 服务端校验token合法性后,把用户信息挂载到socket.user上,和原有Express鉴权中间件逻辑保持一致。

客户端封装改造

基于全局挂载的Socket实例,封装和axios调用方式完全一致的工具,返回Promise实例支持.then()、.catch()链式调用。

封装工具代码

// 单独封装为socketApi.js
import { useContext } from 'react'
import { AuthContext } from './你的AuthContext文件路径'

export const useSocketApi = () => {
  const { socket } = useContext(AuthContext)

  // 通用请求方法
  const request = (method, path, data = {}) => {
    return new Promise((resolve, reject) => {
      // 发送Socket请求,等待服务端ack回调
      socket.emit('post:request', method, path, data, (res) => {
        // 和axios逻辑对齐:2xx状态码视为成功,其余视为失败
        if (res.status >= 200 && res.status < 300) {
          resolve(res.data)
        } else {
          // 错误结构和原有axios catch返回的结构完全对齐
          reject({
            response: res,
            message: res.data.error || '请求失败'
          })
        }
      })
    })
  }

  // 暴露四个方法,调用规则和axios完全一致
  return {
    get: (path, params) => request('GET', path, params),
    post: (path, data) => request('POST', path, data),
    put: (path, data) => request('PUT', path, data),
    delete: (path, data) => request('DELETE', path, data)
  }
}

调用示例

和原有axios的使用方式完全相同,不需要修改业务逻辑:

// 组件内调用
const socketApi = useSocketApi()

socketApi.post('/post/create', { title: '测试', content: '测试内容' })
  .then(post => {
    // 原有axios then的逻辑直接复用
    console.log('创建成功', post)
  })
  .catch(err => {
    // 原有axios catch的逻辑直接复用
    console.error('创建失败', err.message)
  })

原有监听逻辑修复

你之前的useEffect缺少依赖数组,每次组件渲染都会触发Socket断开重连,修改为:

const {socket} = useContext(AuthContext);
useEffect(() => {
  socket.on("connect", () => {
    console.log("client connected")
  })
  // 不要在业务组件内调用socket.disconnect(),全局Socket保持长连接即可,仅在用户登出时断开
}, [socket])

内容的提问来源于stack exchange,提问作者Rajanboy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 16:36:04