==> 服务端促使客户端退出的小案例。
1 安装与配置
1.1 安装依赖包
# 1 egg 项目中安装
npm install egg-socket.io
# 2 vue 项目中安装
npm install vue-socket.io
1.2 配置 egg.js
config/config.default.js
module.exports = appInfo => {
const config = exports = {};
......
// 关闭 csrf
config.security = {
csrf: {
enable: false,
},
};
// cors 跨域配置
config.cors = {
origin: '*',
// 允许请求的方法
allowMethods: 'GET,HEAD,PUT,POST,DELETE,PATCH,OPTIONS',
};
// ************** socket.io 配置 **************
config.io = {
init: {},
namespace: { // 命名空间
'/': { // 可通过 app.io.of('/') 获取到这个命名空间,下面代码中有用到
// 对应下面的 app/io/middleware/connection.js
connectionMiddleware: [ 'connection' ],
// 对应下面的 app/io/middleware/packet.js
packetMiddleware: [ 'packet' ],
}
}
};
// *******************************************
return {
...config
};
}
config/plugin.js
module.exports = {
......
......
io: {
enable: true,
package: 'egg-socket.io',
},
};
app/io/middleware/connection.js
/**
* 在每一个客户端连接或者退出时发生作用
* @param app
* @returns {(function(*, *): Promise<void>)|*}
*/
module.exports = app => {
return async (ctx, next) => {
ctx.socket.emit('res', 'connected!');
console.log('server socket connected');
await next();
};
};
app/io/middleware/packet.js
/**
* 对消息进行预处理
* @param app
* @returns {(function(*, *): Promise<void>)|*}
*/
module.exports = app => {
return async (ctx, next) => {
ctx.socket.emit('res', 'packet received!');
console.log('packet:', ctx.packet);
await next();
};
};
2 egg.js 中 websocket 使用
class AdminController extends Controller {
......
// 其他代码
......
/**
* @description: 修改用户信息
* @param {*}
* @return {*}
*/
async update() {
const { ctx, app } = this;
// =================== 引入 nsp,用于 websocket 相关操作 ===================
const nsp = app.io.of('/'); // 获取到对应的命名空间的内容
// =====================================================================
let res;
const reqBody = ctx.request.body;
if (reqBody.type === 'rename') {
// 重命名
res = await ctx.service.admin.rename(ctx.params.id, reqBody);
} else if (reqBody.type === 'editPassword') {
// 重置密码
res = await ctx.service.admin.editPassword(ctx.params.id, reqBody);
} else if (reqBody.type === 'editStatus') {
// 设置用户状态
res = await ctx.service.admin.editStatus(ctx.params.id, reqBody);
if (res) {
if (reqBody.userStatus === 2 || reqBody.userStatus === 3) {
// ====================== 发送消息 ======================
nsp.emit('logout', { msg: 'logout', id: ctx.params.id });
// ====================================================
}
}
}
if (res) {
ctx.body = new SuccessResponse(null, '修改成功')
} else {
ctx.body = new ErrorResponse(null, '修改失败')
}
}
......
// 其他代码
......
}
3 vue 中使用 websocket
main.js
// 引入 websocket
import VueSocketIO from 'vue-socket.io'
// 配置
const vueSocketIO = new VueSocketIO({
debug: true,
// 后端服务地址
connection: 'http://127.0.0.1:7001',
})
// 监听connect事件
vueSocketIO.io.on('connect', () => {
console.log('socket connect from main.js');
});
Vue.use(vueSocketIO)
home.vue
<script>
......
export default{
sockets: {
// 连接事件
connect: function() {
console.log("socket connect from HOME page");
},
// 登出事件
logout: function(data) {
console.log("wesocket-logout", data);
if (data.id === sessionStorage.getItem("userId")) {
this.$notify.error({
title: "您的账号已被停用/注销/删除!"
});
console.log("我退出了");
this.logout();
}
}
},
data(){...}
}
</script>
4 参考文献
[1] vue-socket.io使用教程与踩坑记录.
[2] egg-socket在egg中的使用.