【问题标题】:How to reconnect a websocket connection after manual close - Vue手动关闭后如何重新连接websocket连接 - Vue
【发布时间】:2018-12-02 20:19:17
【问题描述】:

这是我打开/关闭套接字连接的方法:

methods: {
  connect () {
    this.$socket.onopen = () => {
      this.status = 'connected'
      this.$socket.onmessage = ({data}) => {
        this.$socket.send(this.message)
        console.log({ event: "Recieved message", data })
      }
    }
    this.$socket.onclose = (e) => {
      console.log('Socket is closed. Reconnect will be attempted in 1 second.')
      setTimeout(() => {
        this.connect()
      }, 1000)
    }
  },
  disconnect () {
    this.$socket.close()
    this.status = 'disconnected'
  }
}

我没有使用 socket.io 等,只是内置在 Websocket 对象中。 当我手动调用disconnect () 方法时 - 它按预期关闭连接,但是当我再次发送消息时 - 它说连接已关闭。由于我在挂载中调用connect (),因此如果我不刷新页面,它将不会重新连接。

我尝试过使用观察者:

watch: {
  '$socket': 'connect'
}

但是没有效果。有没有办法监视 websocket 连接状态?如果它已关闭 - 调用 connect (),如果它出错 - 调用 connect () 重新连接它。

【问题讨论】:

  • 内置 WebSocket 对象使用就绪状态,就像其他 HTML API 一样。您可以收听 readystate 3 - 已关闭。然后创建一个新连接。
  • 你的意思是在观察者中?

标签: javascript vue.js


【解决方案1】:

您的 connect() 方法不会“重新连接”到 WebSocket 服务器。所以调用this.connect() 只是重写你的onopen 处理程序。

您必须采取必要的步骤重新连接到 WebSocket 服务器。这个问题的最出色的答案很好地解释了您的代码的良好结构:

vue: emitting global events from websocket listener

很遗憾,它没有回答您的具体问题。因此,我从该答案中分叉了沙箱,并在下面添加了修改后的代码,以便您实现目标。

import Vue from "vue";

const url = "wss://echo.websocket.org";
let socket;

const emitter = new Vue({
  methods: {
    send(message) {
      if (1 === socket.readyState) socket.send(message);
    },
    close() {
      if (1 === socket.readyState) {
        emitter.$emit("message", "Closing Socket.");
        socket.close();
        socket = null; // prevent memory leak
      }
    },
    connect() {
      socket = new WebSocket(url);
      socket.onmessage = function(msg) {
        emitter.$emit("message", msg.data);
      };
      socket.onerror = function(err) {
        emitter.$emit("error", err);
      };
      emitter.$emit("message", "Openning Socket.");
    }
  }
});

emitter.connect();

export default emitter;

要了解如何使用此服务,请查看运行示例中的index.jshttps://codesandbox.io/s/ry4993q654

【讨论】:

  • 谢谢,我注意到我的connect() 没用,因为我没有使用new Websocket() 实例打开它。您的回答建议创建一个新文件,例如socket.js 并将其导入我的组件中?比如import emitter from './socket' 如果我只想在用户登录的情况下打开连接怎么办?
  • 参考新文件问题,看codesanbox中解决方案的结构。那应该回答这个问题(import Socket from './socket')。参考登录用户:在您的登录成功处理程序中调用Socket.connect()
  • 顺便说一句,你所做的,叫做事件总线(发布/订阅模式)?
  • 而且它是现代异步环境中的一种常见模式——比如浏览器。
  • 我可以再问你一个关于connect() 方法的最后一行的问题:emitter.$emit("message", "Openning Socket."); - 它有什么用途?此外,您多次使用相同的事件名称message,如果我为message 事件设置一个侦听器,那么它会侦听所有这些事件吗?
猜你喜欢
  • 2012-11-27
  • 1970-01-01
  • 2014-04-21
  • 1970-01-01
  • 2017-12-04
  • 2023-03-03
  • 2012-02-21
  • 1970-01-01
相关资源
最近更新 更多