最近用uniapp做了一个h5和app的即时通讯软件,在vuex中封装的websocket, 这个是store中index.js的代码
import Vue from 'vue'
import Vuex from 'vuex'
import getters from './getters'
Vue.use(Vuex)
let heartBeatInterval = null
export default new Vuex.Store({
state: {
socketTask: null,
wsMessage: {},
// 47.243.34.252 正式地址
wsUrl: `wss://www......com/im?token=${uni.getStorageSync('token')
}`,
isAddFriendState: false,
appThis: undefined
},
mutations: {
SET_WS_INIT(state, data) {
state.wsMessage = data
},
SET_WS_URL(state, data) {
state.wsUrl = data
},
SET_ADD_FRIEND_STATE(state, data) {
state.isAddFriendState = data
},
SET_THIS(state, data) {
state.appThis = data
}
},
actions: {
wsInit({ state, dispatch }, url = state.wsUrl) {
if (state.socketTask) {
return false
}
state.socketTask = uni.connectSocket({
url,
success: () => { },
fail: (e) => {
console.error('连接失败' + e)
setTimeout(() => {
dispatch('wsInit')
}, 3000)
},
})
state.socketTask.onOpen(() => dispatch('wsOnOpen'))
state.socketTask.onMessage((res) => dispatch('wsOnMessage', res))
state.socketTask.onClose((e) => dispatch('wsOnClose'))
state.socketTask.onError((e) => dispatch('wsOnError'))
},
wsOnOpen({ dispatch }) {
clearInterval(heartBeatInterval)
heartBeatInterval = setInterval(() => {
dispatch(
'wsSend',
JSON.stringify({
act: 'online',
token: uni.getStorageSync("token")
})
)
}, 10000)
},
wsOnMessage({ state, commit, dispatch }, res) {
let data = res && JSON.parse(res.data)
let _this = state.appThis
if (data.ret === -1) {
dispatch('wsClose')
uni.showModal({
title: _this.$t('api.message'),
content: _this.$t('Login has expired. Please log in again'),
cancelText: _this.$t('cancel'), // 取消按钮的文字
confirmText: _this.$t('confirm'), // 确认按钮文字
showCancel: false,
success: (res) => {
if (res.confirm) {
uni.reLaunch({
url: '/pages/login/login',
})
}
},
})
return false
}
if (data.msg !== 'online' && data.msg !== 'success') {
commit('SET_WS_INIT', data || null)
dispatch('msgDealWith', data)
}
},
wsOnClose({ }) {
console.error('WebSocket连接关闭')
},
wsOnError({ }) {
console.error('WebSocket连接错误')
},
wsClose({ state }) {
if (!state.socketTask) return
state.socketTask.close({
success(res) {
clearInterval(heartBeatInterval)
heartBeatInterval = null
state.socketTask = null
},
fail(err) {
console.error('关闭失败', err)
},
})
},
wsSend({ dispatch, state }, data) {
uni.sendSocketMessage({
data,
success: (res) => { },
fail: (e) => {
console.error('发送失败', e)
clearInterval(heartBeatInterval)
heartBeatInterval = null
state.socketTask = null
dispatch('wsInit')
},
})
},
msgDealWith({ commit }, data) {
/**
*ps:这个消息内容就看具体的需求和后端返回值
* global_room_msg_add: 新消息推送 (其中一个对应的会话id的新消息) v1
* global_init_room: 初始会话消息
* global_room_user_add: 新用户加入会话 v1
* global_room_user_edit:用户信息更改
* global_room_msg_edit: 原消息变更推送
* users_friend_apply: 好友申请消息 v1
* room_new_msg: 新消息 (会话内页时候获取最新的消息列表)v1
*/
let list = [
'global_room_msg_add',
'global_init_room',
'global_room_user_add',
'global_room_user_edit',
'global_room_msg_edit',
'users_friend_apply',
'room_new_msg',
'global_update_room',
]
let s = list.find((_) => {
return _ === data.msg
})
if (s) {
console.log('新消息:', data)
uni.$emit(s, data)
if (s === 'users_friend_apply') {
console.log('123')
commit('SET_ADD_FRIEND_STATE', true)
uni.setTabBarBadge({
index: 1,
text: '1',
success:(res)=>{
console.log(res)
},
fail:(err)=>{
console.log(err)
}
})
}
} else uni.$emit('other', data)
},
},
})
这个是getters.js中的
const getters = {
token: state => state.user.token,
}
export default getters
在页面中的用法就是这样子
// 监听消息变化 主要是撤回消息
uni.$on('global_room_msg_edit', (option) => {
this.listData.forEach((_, num) => {
if (_.id === option.data.message.id) {
_.status = 2
this.msgWrapUpdateTop()
}
})
})
逻辑代码就看主要的功能需求是哪些了 ps:要注意在注销自定义事件
onUnload() {
uni.$off('global_room_msg_add')
uni.$off('room_new_msg')
uni.$off('global_room_msg_edit')
},
beforeDestroy() {
uni.$off('global_room_msg_add')
uni.$off('room_new_msg')
uni.$off('global_room_msg_edit')
},
|