promise让websocket发收同步
前端使用websocket收发数据时,不像ajax那样写callback,也不好封装。向后台发送数据后,需要在onmessage中传入callback,发送与接收的代码不能写在同一个方法中,这种异步写法往往会使得项目代码非常松散凌乱,可阅读行很差。
使用promise封装websocket,使得发送数据后同步等待,后端发回数据后,再继续执行后续操作,可以解决这个问题。
这种方法的前提是,你需要知道websocket接到的消息和你发送的消息的对应关系。
解决思路:
new一个promise,将resolve和将要收到的websocket的数据标志key添加到一个数组,onmessage后,根据onmessage的内容在数组中找到与之对应的resolve,调用resolve把数据带回。
class ws = {
constructor(wsServer){
super();
this.wsServer = wsServer
this.wSock = null;
this.pool = {}; // 使用对象代替数据便于查到
}
init = async (onMessage, onError, onClose) => {
return new Promise((resolve, reject) => {
if (!window.WebSocket) { reject('浏览器不支持WebSocket'); }
try {
this.wSock= new WebSocket(this.wsServer);
} catch(err) {
reject(err);
}
this.wSock.onopen = this._onOpen(resolve);
this.wSock.onmessage = this._onMessage(onMessage);
this.wSock.onclose = this._onClose(onClose);
this.wSock.onerror = this._onError(onError);
})
}
_onOpen = resolve => (e) => { resolve(e) }
_onMessage = onMessage => (e) => {
const key = e.data.key;
// 如果pool中有对应key
if (this.pool[key]) {
this.pool[key].resolve(e.data);
delete this.pool[key];
return;
}
// 通知类的处理逻辑使用onMessage处理
onMessage(e);
}
_onClose = onClose => (e) => { onClose(e) }
_onError = onError => (e) => { onError(e) }
_send = async (req, recKey) => {
this.wSock.send(req);
if (typeof recKey !== 'undefined') {
return new Promise((resolve, reject) => {
this.pool[recKey] = {
req,
resolve,
reject,
//...
}
})
}
}
login = async (req) => {
return await this._send(req, 'loginRes')
}
}
调用示例
import ws from './ws';
class Demo {
constructor(){
super();
this.ws = new ws('wss://ws.example.com');
}
init = () => {
this.ws.init(this.onMessage, this.onError, this.onClose)
}
onMessage = () => {}
onError = () => {}
onClose = () => {}
login = async () => {
const req = {};
const res = await this.ws.login(req);
console.log(res);
}
}