从WebSocket监听器发出全局事件 [英] Emitting global events from websocket listener

查看:160
本文介绍了从WebSocket监听器发出全局事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为一个项目做贡献-它是用Vue编写的,而且我是Vue的初学者.

I want to contribute to a project - it's written in Vue, and I am a beginner in Vue.

我有两个组件- Setup MainApp

两者都需要根据来自websocket的不同消息来更新某些状态.一些网络套接字消息会影响前者,而某些则会影响后者.

Both will need to update some state based on different messages from the websocket. Some websocket messages will affect the former, some the latter.

Vue不知道服务,所以我想我只是用空的< template> 创建一个自定义组件.每次在侦听器中出现新消息时,都在此处实例化websocket,然后发出 this.emit().

Vue doesn't know services, so I thought I'd just create a custom component, with empty <template>. instantiate the websocket there and then issue an this.emit() every time a new message occurs in the listener.

其他两个组件都将侦听发射并能够做出反应.

Both other components would listen to the emits and would be able to react.

不幸的是,我无法使websocket组件正常工作.

Unfortunately, I can't get the websocket component to work.

main.js:

import Ws from './WsService.vue';
//other imports

const routes = [
  //routes
]


const router = new VueRouter({
  routes // short for `routes: routes`
})   

const app = new Vue({
  router
}).$mount('#app')
//I thought this to be the way to instantiate my webSocket service:
const WsService = new Vue({
  el: '#WsService',
  components: { Ws }
});

index.html

index.html

  <body>
    <div id="app">
      <div id="WsService"></div>
      <router-link to="/setup">Setup</router-link>
      <router-link to="/main-app">Main App</router-link>
      <router-view></router-view>
    </div>
    <script src="/dist/demo-app.js"></script>
  </body>

websocket的服务":

the websocket "service":

<template>
</template>

<script>
const PORT_LOCAL = 9988; 
var ws = new WebSocket("ws://localhost:" + PORT_LOCAL);
ws.onopen = function() {
     ws.send('{"jsonrpc":"2.0","id":"reg","method":"reg","params":null}');
};

ws.onerror =  function(e) {
      console.log("error in WebSocket connection!");
      console.log(e);
};

export default {

  data() {
    return {
    }
  },

  created() {
    var self = this;
    ws.onmessage =  function(m) {
          var msg = JSON.parse(m.data);
          switch(msg.id) {
            // result for address request
            case "reg": 
              self.$emit("reg_received", msg.result);
              break;
            case "send":
              self.$emit("send_received", msg.result);
              break;
            case "subscribe":
              self.$emit("subscribe_received", msg.result);
              break;
            default:
              console.log(msg);
              break;
          }
    }
  },

  methods: {
  },

  send(id, method, params) {
     ws.send('{"jsonrpc":"2.0","id":"' + id + '","method":"' + method + '","params":null}');

    }
  }

}
</script>

例如从主应用发送(这似乎可行):

Send for example from main app (this seems to work):

 import WsSvc from './WsService.vue';
 export default {
   data() {
     //
   },
   subscribe() {
     let jsonrpc = "the jsonrpc string";
     WsSvc.send(jsonrpc);
   }
 }

发射:

 export default {
   data() {
     //
   },
   created() {
     this.$on("reg_received", function(result){
       //do smth with the result
     });

   }
 }

通过这种配置,实际上不会调用 created 钩子-因此,我将永远不会点击 onmessage 侦听器.我认为拥有自定义组件的原因是我可以访问 emit 函数.

Wit this configuration, the created hook actually never gets called - and thus I'll never hit the onmessage listener. The reason to have a custom component I thought was that I would have access to the emit function.

感觉我正在使它变得比它应该的复杂,但是我还没有设法使它正确.该解决方案不需要遵循这种方法.

It feels I am making it more complicated than it should be but I haven't managed yet to get it right. The solution doesn't need to follow this approach.

推荐答案

在这种情况下,不需要套接字特定的 component .我过去在几个项目上所做的工作是实现一个处理套接字消息的API或存储对象,然后将该API或存储导入需要它的组件中.同样,在类似的答案中,我展示了如何将WebSocket与Vuex集成.

There's no need for a socket specific component in this case. What I have done in the past on a couple projects is implement an API or store object that handles the socket messages and then import that API or store into the components that need it. Also in a similar answer, I show how to integrate a WebSocket with Vuex.

这里是一个示例,该示例将使用Vue作为事件发射器的概念与可导入任何组件的Web套接字结合在一起.该组件可以订阅并收听其要收听的消息.以这种方式包装套接字可以将原始套接字接口抽象化,并允许用户以更典型的Vue方式处理$ on/$ off订阅.

Here is an example that combines the concept of using Vue as an event emitter with a web socket that can be imported into any component. The component can subscribe and listen to the messages it wants to listen to. Wrapping the socket in this way abstracts the raw socket interface away and allows users to work with $on/$off subscriptions in a more typically Vue fashion.

Socket.js

import Vue from "vue"

const socket = new WebSocket("wss://echo.websocket.org")

const emitter = new Vue({
  methods:{
    send(message){
      if (1 === socket.readyState)
        socket.send(message)
    }
  }
})

socket.onmessage = function(msg){
  emitter.$emit("message", msg.data)
}
socket.onerror = function(err){
  emitter.$emit("error", err)
}


export default emitter

这是在组件中使用该代码的示例.

Here is an example of that code being used in a component.

App.vue

<template>
  <ul>
    <li v-for="message in messages">
      {{message}}
        </li>
    </ul>
</template>

<script>
    import Socket from "./socket"

    export default {
        name: 'app',
        data(){
            return {
                messages: []
            }
        },
        methods:{
          handleMessage(msg){
             this.messages.push(msg) 
          }
        },
        created(){
            Socket.$on("message", this.handleMessage)
        },
        beforeDestroy(){
            Socket.$off("message", this.handleMessage)
        }
  }
</script>

这是一个工作示例.

这篇关于从WebSocket监听器发出全局事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆