0
(0)

Nesta publicação concluiremos a criação de nossa aplicação bidirecional utilizando o SocketIo e o microframework Flask. Vamos lá!

Vamos começar implementando em nosso arquivo home.html a biblioteca SocketIo do Javascript. Altere o código como a seguir:

  <body>
<!-- Adicione a tag a seguir também -->
<input type="hidden" id="id" value="{{ id }}">
<!-- Até aqui -->
<textarea name="text" id="text">{{ text }}</textarea>
<!-- Adicione a linha abaixo no código -->
<script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.slim.js"></script>
<!-- Até aqui -->
<script></script>
</body>
</html>

Emitindo os dados para o backend

Agora que adicionamos o arquivo socket.io.slim.js em nosso html, vamos adicionar o código a seguir dentro da tag scripts para que nosso sistema envie para o backend as informações toda vez que um usuário digitar alguma coisa.

<script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.slim.js"></script>
<!-- Adicione o código a seguir após o arquivo da biblioteca socketio -->
<script>
// Método que irá pegar o ip do usuário
const getUserIp = async () => {
const result = await fetch('https://ipapi.co/json/', {
method: 'GET'
});
return await result.json().ip;
}

// Variáveis declaradas
const socket = io.connect(),
ip = getUserIp(),
userSession = `${ip}_${parseInt(Math.random() * 1000)}`;

// Método que irá enviar para o backend tudo que for digitado.
const getText = async () => {
socket.emit('writeReader', {
id: document.getElementById("id").value,
ip,
userSession,
text: document.getElementById("text").value
});
}

// Evento de keyup que é acionado toda vez que o usuário apertar uma tecla.
window.addEventListener("keyup", (event) => {
getText();
});
</script>
<!-- Até aqui -->

Perceba que criamos um método que pegará a cada toque no teclado a informação que estiver no textarea e enviará para o backend. Agora precisamos criar um evento que escute essa emit em nosso backend. Vamos adicionar o código à seguir em nosso app.py.

from flask import Flask, render_template, Response, json, redirect
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
from flask_socketio import SocketIO, emit

from controller import Controller

app = Flask(__name__)
# Adicione a linha a seguir
cors = CORS(app)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///sqlite.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)
db.init_app(app)

# Adicione a linha a seguir
socketio = SocketIO(app)


@app.route('/')
@app.route('/<int:id>')
def index(id=None):
controller = Controller()
document = controller.getDocument(id)

if id == document.id:
return render_template("home.html", id=document.id, text=document.text)
else:
return redirect('/{}'.format(document.id))# Adicione a linha a seguir em seu código
@socketio.on('writeReader')
def writeReader(data):
controller = Controller()
controller.createUpdateDocument(data['id'], data['text'])

# Até aqui if __name__ == '__main__':
# Altere a linha a seguir para usar a instância do socketio
socketio.run(app)

cors = CORS(app) permitirá que adicionemos nossa api de qualquer lugar. Fique atento a esse recurso. Dependendo do que você esteja fazendo você deve bloquear a aplicação para que seja acessada apenas pelas urls específicas. Aqui não iremos afundo nesse assunto.

Em uma de nossas linhas também chamamos socketio = SocketIO(app) que cria o objeto do SocketIo para que possamos lá embaixo iniciar nossa aplicação utilizando ele como vemos na linha socketio.run(app).

Perceba que criamos algo parecido com a rota do através do @socketio.on(‘writeReader’), porém ele não é uma rota e sim um evento que recebe as emissões do html. O método socket.emit(‘writeReader’) que criamos no html chamará esse @socketio.on e executará o método que atualizará um documento específico. Se tentarmos alterar o texto veremos que em nosso banco de dados o documento sofrerá alterações. Veja.

Image for post
Image for post

Podemos ver que a emissão está funcionando, mas ainda temos um porém. Precisamos fazer com que as alterações sejam emitidas para os usuários que estiverem com o mesmo documento aberto. Para isso precisamos adicionar mais algumas linhas de código em nosso html e nosso app.py. Vamos começar abrindo o arquivo python.

@socketio.on('writeReader')
def writeReader(data):
controller = Controller()
controller.createUpdateDocument(data['id'], data['text'])
# Adicione a linha a seguir
emit('writeReader', data, broadcast=True)

O método emit irá devolver os dados alterados para todos que estiverem pronto a ouvir ‘writeReader’. Assim como o html(frontend) emit e o backend ouve, temos aqui o backend emitindo e faremos com que o html ouça essa emissão. O parâmetro data irá conter todas as informações que foram enviadas e que os usuários vão precisar para atualizar seus htmls e o parâmetro broadcast igual a True diz que esse evendo deverá ser emitido para todos que estiverem o escutando. Vamos agora alterar o html para que ele escute o emit do backend.

window.addEventListener("keyup", (event) => {
getText();
});

// Adicione abaixo do método keyup
window.addEventListener('DOMContentLoaded', () => {
socket.on('writeReader', (data) => {
if((ip !== data.ip && userSession !== data.userSession)){
document.getElementById("text").value = data.text;
}
})
})
// Até aqui

Nesta parte do código estamos dizendo que após o conteúdo da página terminar de carregar, iremos acionar a instância do socketio para ficar ouvindo o writeReader através do método on. O que eu faço dentro já é algo customizado. Para evitar do próprio usuário ter sua área de texto renderizada, já que o socketio está emitindo a informações para todos, nós verificamos se o ip e o userSession que estão no data são o mesmo do usuário que está recebendo a emissão (Lembrando que vários usuários que estiverem no mesmo documento estarão recebendo a emissão, inclusive quem enviou a mudança para o backend), caso seja esse usuário não terá seu conteúdo renderizado, já os demais terão. Se você tirar esse verificação vai perceber seu conteúdo bugando toda vez que você edita, porque você vai editar, emitir para o backend e o backend quando emitir para todos, também emitirá para você de volta, ai vai ser você e o back escrevendo no mesmo arquivo. Por isso deixe essa verificação.

Você pode criar qualquer modelo para verificar se o usuário é o mesmo que enviou, uma hash de seção, o storage de login salvo etc, mas precisa ser um identificador único naquele navegador.

Com isso temos nosso sistema funcionando e se você abrir o documento em duas abas diferentes (Inclusive recomendo que uma seja aberta na anônima) você já verá o documento sendo editado bidirecionamento.

Com isso concluímos nossa aplicação com comunicação bidirecional! Espero que tenha curtido… Não esqueça de dar aquela força curtindo a postagem com 5 estrelas e compartilhando.

O que você achou disso?

Clique nas estrelas

Média da classificação 0 / 5. Número de votos: 0

Nenhum voto até agora! Seja o primeiro a avaliar este post.

Compartilhar.

Sobre o autor

Full-Stack Developer e Software Engineer, especialista em Python e JavaScript, professor e palestrante de assuntos voltados à programação web, desktop e mobile, ciência de dados entre outros assuntos. Escritor dos Livros Python de A a Z e Flask de A a Z.

Deixe uma resposta

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.