首次遇见了需要使用到了全双工通信的开发需求,以下是关于 websocket 在我的实际项目中的配置代码。
我司是一家医疗机构,所以遇到了顾客上门分诊的需求,顾客在前台扫码进行填写相关信息后,会同步显示在前台的客户端中,根据新客或者老客的标签来给他进行顾问的选择等。由于需要同步显示,需要服务器主动发送数据到客户端,客户端被动接收。
没有 websocket 之前,会通过定时刷新或者通过前端做假进度来实现,但是前者多余的请求相应会带来更多的资源消耗;后者可能会导致信息传递不及时。
使用 React + ant design + sockJS + stompJS
具体配置如下:
// 引入使用SockJS
import SockJS from "sockjs-client";
import Stomp from "stompjs";
import { Message } from "stompjs";
import moment from 'dayjs'
// 请求地址
const baseUrl = "你自己的 websocket 请求代码";
// 请求头
// const header = {};
// stomp客户端
export let stompClient: Stomp.Client;
// 连接状态
let connetStatus = false;
/**
* 初始化连接
*/
export const initSocket = (data?: any, setData?: any) => {
if (!connetStatus) {
con(data, setData);
}
setInterval(() => {
// 根据连接状态
if (connetStatus) {
try {
// 发送请求
} catch (error) {
con(data, setData);
}
}
}, 5000);
};
/**
* 连接
*/
export const con = (data?: any, setData?: any) => {
let socket: WebSocket = new SockJS(baseUrl);
stompClient = Stomp.over(socket);
stompClient.heartbeat.incoming = 0;
stompClient.heartbeat.outgoing = 5000;
let header = {};
stompClient.connect(
header,
() => {
let today = moment().format('YYYY-MM-DD')
let yesterday = moment().subtract(1, 'day').format('YYYY-MM-DD')
connetStatus = true;
// 设置订阅
if (today !== yesterday) {
stompClient.subscribe(
"/topic/all",
async (res: Message) => {
if (res.body) {
let customerList: any = localStorage?.getItem('customerList')
await setData([
JSON.parse(res.body),
...JSON.parse(customerList ? customerList : '[]'),
]);
speechInfo().start('你有新的顾客来了')
}
},
// header(sub-id)
{ id: 'customer-subid' }
);
}
},
(err: any) => {
console.log("error", err);
}
);
};
/**
* 断开
*/
export const close = () => {
if (stompClient) {
stompClient.disconnect(() => {
stompClient.unsubscribe('customer-subid')
console.log("websocket 连接断开!");
connetStatus = false;
});
}
};
// 语音播报
const speechInfo = () => {
let speechInstance = new SpeechSynthesisUtterance();
return {
// 语音播报开始
start: function (content: string) {
let lang = 'zh-CN'; // zh-HK zh-CN zh-TW
let text = content;
if (text !== '') {
speechInstance.text = text;
speechInstance.lang = lang;
speechInstance.volume = 1;
speechInstance.rate = .9;
speechSynthesis.speak(speechInstance);
speechInstance.onend = function (event) {
console.log("语音播报完毕");
}
}
},
// 暂停
pause: function () {
speechSynthesis.pause();
},
// 重新开始
resume: function () {
speechSynthesis.resume();
},
// 取消
cancel: function () {
speechSynthesis.cancel();
}
}
};
当有顾客上门扫码后,会主动语音播报前台服务人员,以此去为顾客进行分诊管理。语音播报用了 speechSynthesis 这个 api,语音合成接口,但是在 Chrome 浏览器中,需要用户有交互行为,才能自动播放,正在想办法解决此问题。
这是我第一次接触 websocket,后端同事也是首次接触,不过通过现在的测试,看起来效果还不错,等到正式接口下来后,希望 bug 不要太过离谱,哈哈哈
我来更新了,这几天新增了分诊抽屉组件,通过表单为顾客分诊,进行后续顾问带去面诊的操作,头部增加新建预约等,搜索功能等待接口中,详情页组件拆分 header 搜索组件用了模糊查询,点击跳转到对应的详情页中,开发了长时间未操作退出等,等待后端接口 ing
等待后续更新!!!