bmasbnz

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);
  }
}

posted on 2020-04-20 22:29  bmasbnz  阅读(1632)  评论(0)    收藏  举报

导航