Integrate SignalR with Vue.js and Vuex

We are currently working on a voting application based on the vue-cli web package template. Since we want to maintain and manage our voting state in a consistent and maintained manner, we intend to use vuex to manage the state. The interaction between the interface and the backend is web-based, and we want to use signalr since it was very good in previous projects. Due to the fact that we are new to vue.js, we need advice on how to perfectly integrate signalr, vuex and vue.js together.

Describe the scenario:

The interface receives an event from our backend to acknowledge that voting is active and can accept selected responses. After some time, we inform the interface that the results are available and display them to the user. In some cases, we could open another survey. It is important that we can disconnect if the document is hidden (visibility of the api page).

Our approach to solving:

In general, I would like to implement a special signal.service for these purposes. This service is responsible for establishing a connection, as well as sending and receiving messages through websockets. Since we cannot make any changes to the vuex repository from a common module, we found out that a vuex plugin would be suitable. The vuex plugin should wrap signalr.

If we get VotingStartEvent, we will unlock the corresponding question and display it to the user. If the user answered this question, we transfer the new state of this question (answer) to the vuex repository. Inside our plugin, we have a mutation subscription, and we will use this subscription to send our vote to the backend. The following snippet illustrates the idea:

var plugin = (store) => {
  // ...
  store.subscribe((mutation, state) => {
    console.log('inside subscription');
    // if vote has answered state, call connection.send() to submit the message to the backend
  });

  connection.received((message) => {
    // ...
    var event = parseEvent(message);
    if (event.type === START) {
      store.commit({type: 'voting', item: 'unlocked'});
    }
    // ...
  });
}

Is this approach good or do you see some room for improvement?

+4
source share
1 answer

Vue.prototype.$pusher = new Pusher('apiKey'). Pusher , . Pusher Vue create, , . , . , , .

var store = new Vuex.Store({
  state: {
    pusher: null
  },
  mutations: {
    saveInstance(state, instance) {
      state.pusher = instance
    }
  },
  actions: {
    initializePusher ({commit}, apiKey) {
      commit('saveInstance', new Pusher(apiKey))
    }
  }
})

Vue.component('live-price', {
  template: '#live-price',
  props: ['pair'],
  data () {
    return {
      price: 'wait for next trade...',
      channel: null
    }
  },
  created () {
    this.channel = this.$store.state.pusher.subscribe('live_trades_' + this.pair)
    this.channel.bind('trade', data => this.price = data.price)
  }
})

new Vue({
  el: '#app',
  store,
  created () {
    this.$store.dispatch('initializePusher', 'de504dc5763aeef9ff52')
  }
})
[v-cloak] { display: none }
<div id="app">
  <live-price pair="btceur">BITCOIN price in EUR:</live-price>
  <live-price pair="ltceur">LITECOIN price in EUR:</live-price>
  <live-price pair="etheur">ETHEREUM price in EUR:</live-price>
  <live-price pair="xrpeur">RIPPLE price in EUR:</live-price>
</div>

<template id="live-price">
  <p>
    <slot></slot>
    <span v-cloak>{{ price }}</span>
  </p>
</template>

<script src="https://unpkg.com/vue@2.5.3/dist/vue.min.js"></script>
<script src="https://unpkg.com/vuex@3.0.1/dist/vuex.min.js"></script>
<script src="https://js.pusher.com/4.1/pusher.min.js"></script>
+2

Source: https://habr.com/ru/post/1688884/


All Articles