需求描述
最近工作中遇到一个从APP扫码登录WEB站的开发需求,想着以为会用ajax轮询的方案,毕竟登录的使用频率不会太高,令人意外的最终和后端确认的是websocket的实现方式.不过借些机会正好恶补下这个以前没用过的"新技术".
websocket介绍
作为web下的长连接技术已经出现很久了,可以方便的在客户端和服务端进行双向通信。相比ajax轮询能更好的节省服务器资源和带宽,并且能够更实时地进行通讯.
方案选择
考虑到以下几点,我们选择了socket.io
- socket.io同时提供了服务端和客户端(socket.io-client)配套解决方案.
- 兼容性不错,IE下也有降级方案.
- 前后端同构,都是javascript
扫码时序图
关键代码
import io from 'socket.io-client';
import QrCodeWithLogo from 'qr-code-with-logo';
export default class QrcodeLogin {
constructor(opts) {
this.socketUrl = opts.socketUrl;
this.connectSocket();
this.oCanvas = document.getElementById('js_canvas');
this.init();
}
init() {
this.emitQrCode();
this.handleSocketEvent();
}
handleSocketEvent() {
this.socket.on('获取二维码', this.getQrCode.bind(this));
this.socket.on('二维码过期事件', (res) => {
// ui变化
this.socket.on('APP扫码事件', (res) => {
// ui变化
})
// 接收登录事件完成登录
this.socket.on('APP登录事件', (res) => {
if (!(res && res.data)) {
return;
}
// 后续处理
});
}
connectSocket() {
this.socket = io(this.socketUrl, {
transports: ["websocket"],
secure: true
});
}
emitQrCode() {
this.socket.emit('获取二维码事件', {/* 传参 */});
}
refreshQrCode() {
this.socket.close();
this.connectSocket();
// 重新绑定事件
this.handleSocketEvent();
this.emitQrCode();
}
getQrCode(res){
QrCodeWithLogo.toCanvas({
canvas: this.oCanvas,
content: res.url,
width: 156,
logo: {
src: 'logo.png',
logoSize: 0.25,
radius: 8
}
}).catch(err=> {
console.log(err);
})
}
}
总结
用了socket方案后,相比ajax轮询代码结构变得更清晰,只须针对服务端推送过来的对应事件编写相应处理逻辑即可。socket重新连接后,socket实例已经变化,需要重新绑定事件处理函数。