浏览器中 SignalR 连接示例及注意事项
1. 浏览器中websocket 不支持自定义请求头, 如果需要自定义请求头, 只能使用 http 方式, 对应配置项: withUrl 第二个参数中增加 transport: SignalR.HttpTransportType.LongPolling 配置。2. token 携带可以使用官方推荐的 accessTokenFactory。3. withUrl 可以使用的配置项。
·
官方文档地址:
ASP.NET Core SignalR configuration | Microsoft Learn
注意事项:
1. 浏览器中websocket 不支持自定义请求头, 如果需要自定义请求头, 只能使用 http 方式, 对应配置项: withUrl 第二个参数中增加 transport: SignalR.HttpTransportType.LongPolling 配置
.withUrl(`/ProductClientMsgHub}`, {
transport: SignalR.HttpTransportType.LongPolling, // 使用 LongPolling
headers: defaultHeaders,
})

2. token 携带可以使用官方推荐的 accessTokenFactory
.withUrl(`/ProductClientMsgHub}`, {
skipNegotiation: true,
transport: SignalR.HttpTransportType.WebSockets,
accessTokenFactory: () => util.cookies.get('token'), // 自动附加 Authorization Bearer
})
3. withUrl 可以使用的配置项

示例代码:
import * as SignalR from "@microsoft/signalr";
import { Notification } from "element-ui";
import util from "@/libs/util.js";
import store from "@/store/index";
let connection = null;
const baseUrl = '192.168.x.x:xxxx'
// 创建连接
const createConnection = (headers = {}) => {
// 设置连接头信息
const defaultHeaders = {
'LineId': headers.LineId || '',
'OperationId': headers.OperationId || '',
'ClientType': headers.ClientType || 'PC',
'OrganizeId': headers.OrganizeId || Number(localStorage.getItem('organizeId')),
'Authorization': `Bearer ${util.cookies.get('token')}`
}
console.log('创建连接,headers:', defaultHeaders)
connection = new SignalR.HubConnectionBuilder()
.configureLogging(SignalR.LogLevel.Information)
.withUrl(`${baseUrl}/ProductClientMsgHub?LineId=${headers.LineId}&OperationId=${headers.OperationId}&ClientType=${headers.ClientType}&OrganizeId=${headers.OrganizeId}`, {
skipNegotiation: true, // 跳过协商
transport: SignalR.HttpTransportType.WebSockets,
// transport: SignalR.HttpTransportType.LongPolling,
withCredentials: true,
// headers: defaultHeaders,
accessTokenFactory: () => util.cookies.get('token'), // 自动附加 Authorization Bearer
})
.withAutomaticReconnect({
nextRetryDelayInMilliseconds: () => {
return 5000; // 每5秒重连一次
},
})
.build();
connection.keepAliveIntervalInMilliseconds = 15 * 1000; // 心跳检测15s
connection.serverTimeoutInMilliseconds = 30 * 60 * 1000; // 超时时间30m
// 断开连接
connection.onclose(async (error) => {
console.log('SignalR 连接断开')
if (error) {
console.error('断开原因:', error)
}
})
// 重连中
connection.onreconnecting((error) => {
console.log('SignalR 正在重连...')
if (error) {
console.error('重连原因:', error)
}
Notification({
title: "提示",
message: "服务器已断线,正在重连...",
type: "warning",
position: "bottom-right",
})
})
// 重连成功
connection.onreconnected((connectionId) => {
console.log('SignalR 重连成功!')
console.log('新的连接ID:', connectionId)
Notification({
title: "提示",
message: "服务器重连成功",
type: "success",
position: "bottom-right",
})
})
return connection;
}
// 启动连接
const startConnection = async (headers = {}) => {
try {
// 如果连接不存在或已断开,创建新连接
if (!connection || connection.state === SignalR.HubConnectionState.Disconnected) {
console.log('正在连接 SignalR 服务...', headers)
connection = createConnection(headers)
await connection.start()
console.log('SignalR 连接成功!')
console.log('连接状态:', connection.state)
console.log('连接ID:', connection.connectionId)
return connection
} else {
console.log('当前连接状态:', connection.state)
return connection
}
} catch (err) {
console.error('SignalR 连接失败:', err)
console.error('错误详情:', {
message: err.message,
stack: err.stack
})
}
}
// 获取连接实例
const getConnection = () => {
if (!connection) {
console.warn('SignalR 连接未创建,请先调用 startConnection')
return null
}
return connection
}
export { getConnection as signalR, startConnection };
最终效果:

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)