Implementando SignalR client Javascript— Utilizando Vue.js

Bruno Seco
3 min readAug 16, 2020

--

Signalr + Vue

Fui lendo vários tutoriais e juntando para conseguir implementar da forma que eu precisava o SignalR no meu client, basicamente meu contexto era…

Eu tenho um usuário logado no meu sistema, ele tem uma ação no sistema que quando ele clica em determinado botão acontece uma ação de PLAY e quando ele clica novamente vira PAUSE, e vice-versa.

Esse mesmo usuário pode estar logado tanto no desktop quanto no seu dispositivo mobile, então essa ação de PLAY quando clicado no desktop, precisa refletir no dispositivo mobile, mas como?

Então decidi implementar o SignalR para manter essa informação na tela em tempo real. Fiz todas as implementações necessárias na minha API e faltou ligar o cliente nesta API, então ficou da seguinte forma:

Estou utilizando Vue.js, mas poderia ser em qualquer framework, como Angular ou React. Será necessário instalar a própria ferramenta do SignalR via npm no seu client

https://www.npmjs.com/package/@aspnet/signalr na própria página já tem vários exemplos de como implementar, mas vamos lá…

npm install @aspnet/signalr --save

Instalado, o que iremos realizar será criar uma classe default para exportarmos e reutilizarmos nos nossos componentes, é interessante que você chame uma única vez e emita eventos dessa classe utilizando as funcionalidades do seu framework, no caso do Vue eu criei um EventBus.

Essa classe abaixo será o nosso “signalrHub.js” que será inicializado no último exemplo de código no final do texto.

Explicando… criei esse export default onde chamarei dentro de algum método quando inicializa minha aplicação e tenho o id do usuário logado já salvo nos Cookies (se desejar verificar o processo dos cookies https://medium.com/@brunoseco/trabalhando-com-cookie-javascript-utilizando-vue-js-92665cabde36).

No método “start()” eu configuro a conexão e chamo o método “connect()” para realizar as tentativas de conectar no meu hub (previamente criado na API)

Neste hub eu crio um grupo novo com o id do usuário para que todos os clientes (dispositivos) que se conectem com o mesmo id de usuário sejam notificados em cada mudança de status (play e pause).

// no backend (hub) o método "SetUser" recebe o id do usuário
// e registra a conexão no grupo do id do usuário - userId
public async Task SetUser(string userId)
{
await Groups.AddToGroupAsync(Context.ConnectionId, userId);
}

Ou seja, se o usuário zezinho (id 123), se logar no desktop e também se logar no celular, ambos irão ser registrados num grupo chamado 123 (que é o id do usuário dele) e serão notificados nas mudanças de status.

Para isso que aconteça esse registro eu faço a chamada

var _userId = Cookie.get("USER_ID");
this.connection.invoke("SetUser", _userId);

E quando o usuário clica em “play” eu chamo uma API para registrar a ação no banco de dados e como último item do método eu notifico todas as conexões

[Authorize]
[HttpPost("StartStop")]
public async Task<IActionResult> StartStop(int userId, int action)
{
var returnModel = await this._service.StartStop();
await _hubContext.Clients
.Group(userId)
.SendAsync("PlayPauseChange", action);
return true;
}

Quando chamado o “SendAsync” com evento “PlayPauseChange”, meus clients que estiverem escutando por este evento serão notificados

this.connection.on("PlayPauseChange", action => {
// trabalho a notificação recebida
Vue.prototype.$eventHub.$emit('play-pause-change', action)
})

E no retorno eu notifico os componentes utilizando o EventBus do Vue https://medium.com/@brunoseco/criando-um-eventbus-no-vue-js-5ae977e41eb8

Vue.prototype.$eventHub.$emit('play-pause-change', action)

Para inicializar o seu hub, chamando o “start()”, você pode implementar em algum mounted ou método após a aplicação ter inicializado e já existir o id do seu usuário

<template>
<div id="app"></div>
</template>
<script>
import signalrHub from 'signalr-hub'
export default {
name: "componente-teste",
mounted() {
signalrHub.start();
},
};
</script>
<style lang="scss"></style>

Tentei deixar o mais direto possível os exemplos, eu implementei num projeto em Vue, porém o modelo é só um conceito que pode ser reaproveitado a mesma classe js para Angular ou outros, é só adaptar a chamada no seu componente.

Obrigado.

--

--

Responses (1)