该应用程序在后台运行超过10分钟后,Websocket关闭。 (本机)

时间:2018-07-23 09:59:28

标签: android ios react-native websocket

我正在使用React-Native创建一个应用程序,并使用websocket接收数据。 但是,当我按下主页按钮使我的应用程序在后台运行时,websocket将被暂停,当我再次单击我的应用程序时,websocket将继续运行,这是完全可以的,但是我的问题是我的应用程序在后台模式下运行超过10次分钟,当我再次打开我的应用程序时,websocket完全停止了。我该如何解决这个问题?

我知道我可以使用Appstate来检测我的应用程序是否处于后台模式。但是我认为那不是我现在真正需要的!

还有另一个类似的问题:

如果用户留在应用程序中但手机自动锁定并且再次打开手机时,websocket也已关闭怎么办。 如何让websocket再次继续?

有什么想法吗?

1 个答案:

答案 0 :(得分:3)

我们有一个使用websockets的应用程序,我们的问题是在重新启动REST服务器的情况下,所有客户端都应重新打开Web套接字。因此,我们使用setInterval以固定速率ping服务器,并在出现错误时重新创建套接字,这是我们的套接字管理器类的代码:

export default class SocketManager {
  constructor(endPoint, handlers) {
    this.endPoint = endPoint;
    this.handlers = handlers;

    this.createSocket();
  }

  createSocket() {
    if (this.interval) clearInterval(this.interval);
    this.socket = this.buildSocket();
    this.pings = 0;
    this.pongs = 0;

    this.interval = setInterval(() => {
      this.socket.send("ping");
      this.pings++;
    }, 3000);
  }

  closeSocket = () => {
    console.log("Cerrando socket");
    if (this.interval) clearInterval(this.interval);
    this.socket.close();
  };

  reconnect = () => {
    this.createSocket();
  };

  buildSocket = () => {
    const sock = new WebSocket(this.endPoint);
    sock.onerror = error => {
      console.log("error", error);
      setTimeout(() => this.reconnect(), 3000);
    };
    sock.onmessage = ({ data }) => {
      if (data === "pong") {
        this.pongs++;
        console.log(`${this.pings} pings, ${this.pongs}  pongs`);
        return;
      }
      const handler = this.handlers[data];
      if (handler) {
        handler();
      }
    };

    return sock;
  };
}

我们是通过redux动作创建者来调用它的,例如:

const doLogin = ({ email, password }) => {
  const body = doFormBody({ email, password });
  // // //console.log(`endPoint es ${ENDPOINT}`);

  return dispatch => {
    dispatch({ type: CONECTANDO });

    const url = `${ENDPOINT}/rest/login`;
    fetch(url, {
      headers: {
        Accept: "application/json",
        "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
      },
      method: "POST",
      body
    })
      .then(response => response.json())
      .then(json => {
        if (json.error) dispatch({ type: LOGIN_ERROR, payload: json.error });
        else {
          dispatch({ type: LOGGED_IN, payload: json });
          const adultosSocket = crearSocket(dispatch, json.id);
          dispatch({ type: ESTABLECE_SOCKET, payload: adultosSocket });
        }
      })
      .catch(err => {
        dispatch({ type: LOGIN_ERROR, payload: err.message });
      });
  };
};

该操作使用此帮助器函数最终创建套接字。随时保持仅一个套接字实例发送ping十分重要。

const crearSocket = (dispatch, userId) => {
  const endPoint = `${WS_ENDPOINT}/usuarioConectado?userId=${userId}`;
  const handlers = {
    reload: () => {
      const url = `${ENDPOINT}/rest/adultos/${userId}`;
      fetch(url)
        .then(response => response.json())
        .then(json => dispatch({ type: ADULTOS_CARGADOS, payload: json }))
        .catch(err => dispatch({ type: ADULTOS_ERROR, payload: err.message }));
    }
  };

  return new SocketManager(endPoint, handlers);
};

这不是玩具代码,实际上在我们的应用程序中运行,因此可以正常工作。