websocket是HTML5开始提供的一种在单个TCP链接上进行全双工通信的协议。大多数 Web 应用程序将经过频繁的异步JavaScript和XML(AJAX)请求实现长轮询。轮询的效率低,很是浪费资源。而websocket可以很好的解决相似的问题。经常使用于即时通信、监控等状况。 在本案例中, 使用egg+typescript做为后端框架, 使用egg官方封装的Socket.IO库。前端使用vue。html
TS下的egg许多设置和文档有所不一样, 可是稍稍看一下仍是能理解的。 按照egg的文件规划,Socket.IO应该独立的做为一个文件夹, 内部包含本身的controller和middleware, 而后和其余页面共享router配置前端
// router
export default (app: Application) => {
const { controller, router, io } = app;
// Socket.IO会经过io暴露出来, io.of('/')则是命名空间
router.get('/', controller.home.index); // 这个是正常的http请求
io.of('/').route('online', io.controller.nsp.exchange); // 这个就是websocket请求
io.of('/').route('newmsg', io.controller.nsp.newmsg);
io.of('/').route('sendMsg', io.controller.nsp.sendMsg);
};
复制代码
// config/plugin 这里是egg开启插件插件的地方
const plugin: EggPlugin = {
// static: true,
nunjucks: {
enable: true,
package: 'egg-view-nunjucks', // 模板渲染插件
},
io: {
enable: true,
package: 'egg-socket.io', // 官方的封装的socke插件
},
};
复制代码
// config/config.default 根据不一样环境, 配置插件参数
export default (appInfo: EggAppInfo) => {
// ...
config.middleware = [];
// 配置模板引擎
config.view = {
cache: false,
defaultExtension: 'nunjucks',
mapping: {
'.html': 'nunjucks',
},
};
// 配置socket
config.io = {
init: { }, // passed to engine.io
namespace: {
// 命名空间
'/': {
connectionMiddleware: [
'connection', // 这个是链接中间件, 只在connection的时候触发
],
packetMiddleware: [], // 这个会在每次消息的时候触发
},
'/example': {
connectionMiddleware: [],
packetMiddleware: [],
},
},
};
return config;
};
复制代码
// app/router
export default (app: Application) => {
const { controller, router, io } = app;
router.get('/', controller.home.index);
// 这里的sendMsg至关于一个接口, 负责处理客户端发送的sendMsg事件
// 这个controller是io模块的controller, 和egg的controller不一样
io.of('/').route('sendMsg', io.controller.nsp.sendMsg);
};
复制代码
// app/io/controller
import { Controller } from 'egg';
export default class NspController extends Controller {
public async sendMsg() {
const { ctx, app } = this;
const nsp = app.io.of('/');
const message = ctx.args[0] || {}
// 向客户端广播消息, 在客户端监听broadcast事件就能够获取消息了
nsp.emit('broadcast', message)
}
}
复制代码
// app/io/middleware/connection
import { Context } from 'egg';
// io模块的中间件, 在config/config.default里配置成connectionMiddleware, 只在
connection的时候触发
export default function robotMiddleware() {
return async (ctx: Context, next: any) => {
const { app } = ctx;
const nsp = app.io.of('/');
// 向客户端推送online事件
nsp.emit('online', '有新成员加入聊天室了')
await next();
};
}
复制代码
这样, 服务器端的逻辑就完成了,接下来经过vue来实现客户端逻辑vue
// 客户端 src/utils/io
import io from 'socket.io-client';
// 稍微封装一下socket.io, 而后暴露出去。
const socket = function ():any {
const _io = io('http://127.0.0.1:7001/');
_io.on('connect', function(){
console.log('连接成功');
});
_io.on('disconnect', function(){
console.log('断开连级');
});
return _io
}
export default socket
复制代码
// 客户端 app/App.vue
export default class Index extends Vue {
// 头像
user = {
avatar: 'https://f12.baidu.com/it/u=4263977612,1595937908&fm=76'
}
// 消息列表
msgList: Array<string> = []
//发送消息, 触发sendMsg事件
sendMsg(msg: string):void {
socket.emit('sendMsg', msg)
}
// 页面加载以后触发
mounted() {
// 监听online事件
socket.on('online', (data: string) => {
this.msgList.push(data)
})
// 监听broadcast事件, 获取服务器消息
socket.on('broadcast', (data: string) => {
this.msgList.push(data)
})
}
}
复制代码
socket是基于事件监听来进行的, 经过on来注册监听事件, 经过emit来触发事件。 经过服务器和客户端的配合, 就能够事件即时的消息推送。这篇文章只写了最简单功能, 基于socket.io还有分房间, 踢人,身份识别,私聊等功能, 等下篇文章再写吧。web