Minicurso Socket.IO – Parte 3 – Recebendo a notificação de Gol

minicurso socket.IO

Nas aulas anteriores do minicurso de Socket.IO, já preparamos o ambiente, conectamos o websocket do client para o servidor e agora vamos começar a emitir realmente as notificações.

A primeira coisa que vamos fazer é enviar o placar, vamos abrir o template match.ejs dentro de admin. A única coisa que temos de diferente é o time e os gols, nós vamos pegar esses dados e quando o usuário clicar em atualizar placar, iremos enviar isso ao servidor e ele vai disparar via socket.io para todos os clients.

Primeiramente lá no final, após incluir o footer, vamos adicionar um script:

<script src="/js/admin.js"></script>

Esse script ainda não existe, vamos criar agora no diretório public/js, primeiro temos que descobrir qual o ID do botão do formulário, que é update-score e quando o usuário clicar nesse botão, eu quero dar um alert apenas para saber se está rodando:

$(function)(){

$("#update-score").click(function(){

alert(1)

return false;

})

});

Agora precisamos pegar os dois valores do jogo nos ID’s score, e score-b, o notify-score e damos um console.log para saber se está tudo correto:

$(function)(){

$("#update-score").click(function(){

const scoreA = $("#score-a").val();

const scoreB = $("#score-b").val();

const notify = $("#score-notify").val();

console.log(scoreA, scoreB, notofy)

return false;

})

});

Perceba que o notify continuou com o value 1, isso acontece porque não está checando se esta checked ou não, então fazemos isso:

const notify = $("#score-notify:checked").val();

Agora precisamos enviar isso para o express para ele distribuir via Socket.IO para todos os clients. Ao invés de mandar essa atualização via Socket.IO, eu posso mandar via API, salvar essa informação no banco e aí sim notificar (eu prefiro usar sempre essa forma para eu garantir  que eu só envie essa notificação para todo mundo).

$(function)(){

$("#update-score").click(function(){

const scoreA = $("#score-a").val();

const scoreB = $("#score-b").val();

const notify = $("#score-notify").val();

$.post("/admin/match/0/score", post {

scoreA, scoreB, notify

}, function(data){

console.log(data)

})

return false;

})

});

Ele não vai conseguir, pois não achou, mas se olharmos a conexão os dados já estão sendo enviados, então temos que receber esses dados lá. Vamos voltar em routes/admin.js e criar novo router:

router.post('/match/:id/score', function(req, res){

res.send(req.body)

})

Fizemos isso para termos certeza que os dados estão chegando aqui, então vamos parar o servidor e a resposta do score vai ser exatamente o que eu enviei para ele, agora podemos processar esses dados. Vamos setar o valor no placar do banco de dados. Uma das formas que temos de fazer isso no low-db é pegando o índice do jogo e setar lá dentro falando qual o valor vou enviar para ele. Essa informação vai para todos os jogos, então eu devo emitir para todos que estão conectados no Socket.IO:

router.post('/match/:id/score', function(req, res){

db.set('matches['+req.params.id+'].team-a.score',

parseInt(req.body.scoreA)).write()

db.set('matches['+req.params.id+'].team-b.score',

parseInt(req.body.scoreB)).write()



io.emit('score', {

match: req.params.id,

scoreA: req.body.scoreA,

scoreB: req.body.scoreB,

notify: req.body.notify || 0

})

res.send(req.body)

})

Se o notify não existir, ele não vai ser enviado e eu mando zero para não notificar meus usuários. Agora está funcionando perfeitamente, se startarmos o servidor e dermos um f5, vai ser mostrado o valor enviado.

Como eu tenho que dar f5 toda hora, tenho que receber no meu client a atualização que o jogo foi alterado, então vamos abrir na pasta js o arquivo match.js:

$(function)(){

const socket = io();

socket.on('connect', function(){

console.log('conected');

})

socket.on('score', function(score){

console.log('score', score)

})

})

Perceba que agora, ao atualizar o placar, o usuário recebe o objeto score, então precisamos checar se o jogo está na barra de cima e se é o jogo atual para atualizar na barra principal. Para isso vamos em match.ejs e na lista de jogo que fica na parte de cima, já temos um forEach que vai renderizar todos os jogos e temos para cada jogo um ‘em’ que tem o nome da class com uma referência para o jogo como um todo. Vamos copiar esse trecho de código em negrito:

<em class="match-<%- index %>-b">

Agora vamos voltar para nosso match do client em js/match.js e fazer o seguinte:

$(function)(){

const socket = io();

socket.on('connect', function(){

console.log('conected');

})

socket.on('score', function(score){

console.log('score', score)

//na lista de jogos

$(". match-"+score.match+"-a").html(score.scoreA)

$(". match-"+score.match+"-b").html(score.scoreb)

})

})

Perceba que em A nós escrevemos o valor de score.scoreA e o mesmo no B. Agora temos que atualizar a parte de baixo também, então nós temos o score-team-A e o valor do score por exemplo, porém como eu vou saber se esse jogo é o que eu estou atualmente? Em match.ejs, lá no final, antes do include do footer, vamos fazer um script que define uma constante:

<script>

const MATCH_INDEX = "<%- id %>";

</script>

Quando faço isso, o match.index consegue acessar esse valor, então dentro do nosso match conseguimos checar se estamos em nosso jogo atual:

socket.on('score', function(score){

console.log('score', score)

//na lista de jogos

$(". match-"+score.match+"-a").html(score.scoreA)

$(". match-"+score.match+"-b").html(score.scoreb)

//  atualizar o jogo

if(MATCH_INDEX == score.match){

$(".score-team-a").html(score.scoreA);

$(".score-team-b").html(score.scoreB);



if(score.notify=='1'){

console.log('notificar')

}

}

})

Se o jogo é o que recebemos a notificação, nós notificamos esse gol.

Em view/match, lá no final, temos uma div que é uma class goooolllll com um áudio, então se estivermos com o notificado ligado vamos dar um play nesse áudio, voltamos no código anterior e adicionamos o seguinte:

if(score.notify=='1'){

console.log('notificar')

$('#audio-gol')[0].currentTime=0;

$('audio-gol')[0].play();

}

Por que fizemos o notificar sim ou não?

É possível notificar um gol e caso ele seja anulado, você tira o notificar e tira o placar sem alarmar todos.

Podemos também fazer uma animação com aquele div que está ali

if(score.notify=='1'){

console.log('notificar')

$('#audio-gol')[0].currentTime=0;

$('audio-gol')[0].play();



$('.goooolllll')addClass('goooolllll-anim')

$('.goooolllll-text')addClass('goooolllll-text-anim')

$('.goooolllll-text')on('transitionend webkitTransitionEnd oTransitionEnd', function(){

$('.goooolllll')removeClass('goooolllll-anim')

$('.goooolllll-text')removeClass('goooolllll-text-anim')

})



}

Para testar temos que notificar em uma outra aba. Ao clicar, aparece duas classes com essa animação, quando a animação terminar nós removemos essa animação.

Na próxima aula vamos colocar a comunicação do lance a lance e dos vídeos, além de colocar o projeto em um servidor no digitalhost para conseguirmos acessar externamente. Confira o passo a passo em vídeo:

Curta o DevPleno no Facebookinscreva-se no canal e não se esqueça de cadastrar seu e-mail para não perder as novidades. Abraço!