123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- import io from 'socket.io-client'
- import { setBaseOption, BaseOption } from './storage'
- import { type SocketOptions, SocketEvent } from './type'
- import { SocketStatus, HskTerminatedCode } from './outputType'
- import EventEmitter from '../eventemitter'
- import { Logger } from '../Logger'
- class HsSocket extends EventEmitter {
- private logger: Logger
- public socket?: typeof io.Socket
- /** 初始化 socket 需要的参数 */
- public socketOptions: SocketOptions
- /** 心跳延迟时间 */
- private heartBeatDelay: number
- /** 主动关闭链接时间 */
- private closeHeartBeatDelay: number
- /** 心跳检测定时器 */
- private heartBeatTimer: null | ReturnType<typeof setTimeout>
- /** 清空心跳检测定时器 */
- private closeHeartBeatTimer: null | ReturnType<typeof setTimeout>
- /** 超时次数 */
- // private timeOutCount: number
- /** 最大超时次数限制 */
- private imRetryCount: number
- /** 本次 socket 会话唯一 id */
- private sessionId: string
- constructor(socketOptions: SocketOptions) {
- super()
- /** 页面关闭时 关闭 socket */
- window.addEventListener('onunload', this.closeSocket)
- this.logger = new Logger(socketOptions.loggerLevel, 'HsSocket')
- this.socket = undefined
- this.heartBeatTimer = null
- this.closeHeartBeatTimer = null
- // this.timeOutCount = 0
- this.sessionId = ''
- this.socketOptions = socketOptions
- this.heartBeatDelay = socketOptions.imHeartTime * 1000 || 3000
- this.closeHeartBeatDelay = socketOptions.imHeartTime * 1000 || 3000
- this.imRetryCount = socketOptions.imRetryCount || 10
- }
- /** @public initSocket 初始化 Socket 连接 */
- public initSocket(): void {
- /** 如果有未断开的连接先断开 */
- this.closeSocket()
- // 设置状态为连接中
- this.emit(SocketEvent.SetSocketStatus, {
- status: SocketStatus.Connecting
- })
- /** https://socket.io/docs/v2/client-api/#iourl */
- this.socket = io(this.socketOptions.imWsServer, {
- transports: ['websocket'],
- reconnectionAttempts: this.imRetryCount,
- reconnectionDelay: this.heartBeatDelay,
- reconnectionDelayMax: this.heartBeatDelay + 1000,
- timeout: this.heartBeatDelay,
- reconnection: true
- })
- /** https://socket.io/docs/v2/client-api/#event-error */
- this.socket.on('error', (error: object) => {
- this.logger.error(`socket_error | ${JSON.stringify(error)}`)
- })
- /** https://socket.io/docs/v2/client-api/#event-connect_error-1 */
- this.socket.on('connect_error', (error: object) => {
- const errorData = `socket_connect_error | ${JSON.stringify(error)}`
- this.logger.warn(errorData)
- })
- this.socket.on('reconnecting', (res: string) => {
- this.logger.error(`socket_warn | socket_reconnecting | ${res}`)
- this.emit(SocketEvent.SetSocketStatus, {
- status: SocketStatus.ReTry
- })
- })
- this.socket.on('reconnect', (res: string) => {
- this.logger.error(`socket_warn | socket_reconnect | ${res}`)
- this.emit(SocketEvent.SetSocketStatus, {
- status: SocketStatus.Ready
- })
- })
- this.socket.on('reconnect_failed', (error: string) => {
- this.logger.error(`socket_warn | socket_reconnect_failed | ${error}`)
- this.emit(SocketEvent.SetSocketStatus, {
- status: SocketStatus.Terminated,
- code: HskTerminatedCode.SocketOnReconnectFailed,
- error: `${error}`
- })
- })
- /** https://socket.io/docs/v2/client-api/#event-connect */
- this.socket.on('connect', () => {
- this.emit(SocketEvent.SetSocketStatus, {
- status: SocketStatus.Connected
- })
- this.socketLogin()
- })
- /** https://socket.io/docs/v2/client-api/#event-disconnect */
- this.socket.on('disconnect', (reason: string) => {
- const errorMessage = `socket_disconnect | ${reason}`
- this.logger.warn(errorMessage)
- })
- /** 服务端下行事件 */
- this.socket.on('common_down_data', (e: string) => {
- // console.log(e, 3434343434)
- if (e && JSON.parse(e) && JSON.parse(e).data) {
- this.emit(SocketEvent.SocketDownEvent, {
- eventData: JSON.parse(JSON.parse(e).data)
- })
- }
- })
- /** 服务端下行指令 */
- this.socket.on('common_down_cmd', (e: string) => {
- const { clientSessionId } = JSON.parse(e)
- // console.log('dsdsdsdsdsds', clientSessionId)
- if (clientSessionId === this.sessionId) {
- this.logger.error(
- `socket status | ${SocketStatus.Terminated} | 坐席在其他页面重新初始化,本页面被踢出`
- )
- this.emit(SocketEvent.SetSocketStatus, {
- status: SocketStatus.Terminated,
- code: HskTerminatedCode.SocketRepeatLogin,
- error: '您已在其他页面签入,当前页面连接已断开'
- })
- }
- })
- }
- /** @private socketLogin 客户端上行登录事件 */
- private socketLogin() {
- const data = {
- // appCode: this.socketOptions.appCode || '1111',
- // token: this.socketOptions.token || '1111',
- userId: this.socketOptions.agent_id
- }
- this.socket &&
- this.socket.emit('login', data, (sessionId: string) => {
- // console.log(sessionId, '测试一下')
- this.emit(SocketEvent.SetSocketStatus, {
- status: SocketStatus.Ready
- })
- setBaseOption(BaseOption.TrackParams, { socket_session_id: sessionId })
- this.sessionId = sessionId
- this.startHeartbeat()
- })
- }
- /** @public closeSocket 关闭 socket 连接 */
- public closeSocket() {
- if (this.socket) {
- this.socket.io.opts.reconnection = false
- this.socket.close()
- // 清除之前的监听事件
- this.socket.removeAllListeners()
- }
- this.socket = undefined
- this.sessionId = ''
- if (this.heartBeatTimer) {
- window.clearTimeout(this.heartBeatTimer)
- this.heartBeatTimer = null
- }
- if (this.closeHeartBeatTimer) {
- window.clearTimeout(this.closeHeartBeatTimer)
- this.closeHeartBeatTimer = null
- }
- }
- /** @private startHeartbeat 开启心跳检测 */
- private startHeartbeat() {
- if (this.heartBeatTimer) {
- window.clearTimeout(this.heartBeatTimer)
- this.heartBeatTimer = null
- }
- if (this.closeHeartBeatTimer) {
- window.clearTimeout(this.closeHeartBeatTimer)
- this.closeHeartBeatTimer = null
- }
- this.socket && this.heartbeatEvent()
- }
- /** @private heartbeatEvent websocket心跳检测 */
- private heartbeatEvent() {
- this.heartBeatTimer = setTimeout(() => {
- this.socket && this.sendHeartbeat()
- /** 如果心跳检测一直没回应,则进行重连 */
- this.closeHeartBeatTimer = setTimeout(() => {
- this.logger.warn('socket_heart_beat | 心跳超时,即将重新连接')
- this.initSocket()
- }, this.closeHeartBeatDelay)
- }, this.heartBeatDelay)
- }
- /** @private sendHeartbeat 客户端上行心跳事件 */
- private sendHeartbeat() {
- this.socket &&
- this.socket.emit(
- 'heartbeat',
- JSON.stringify({
- ...this.socketOptions
- }),
- () => {
- this.startHeartbeat()
- }
- )
- }
- }
- export default HsSocket
|