Ao se deparar com um projeto, basta anotar o conteúdo relevante a propósito.
SSE
A tecnologia Server-Sent Events (SSE) é uma tecnologia da Web usada para enviar dados do servidor para o cliente em tempo real. O SSE é baseado no protocolo HTTP, permitindo que o servidor envie dados para o cliente na forma de fluxo de eventos (Event Stream). O cliente pode receber os dados enviados pelo servidor em tempo real estabelecendo uma conexão HTTP persistente e ouvindo o fluxo de eventos.
SSE e Websockets
O SSE é frequentemente usado em comparação com o Websocket, mas sua base e uso são bem diferentes, como segue:
- SSE é uma comunicação unidirecional do servidor para o cliente, ou seja, após a conclusão da conexão, apenas o back-end pode enviar dados para o front-end e o front-end recebe os dados passivamente. O WebSocket é uma comunicação bidirecional e a troca de dados bidirecional em tempo real pode ser realizada entre o back-end e o front-end.
- O SSE usa uma longa conexão baseada no protocolo HTTP para estabelecer uma conexão por meio de solicitações e respostas HTTP; enquanto o WebSocket usa um protocolo baseado em TCP para obter comunicação bidirecional estabelecendo uma conexão WebSocket.
- O SSE é frequentemente usado em cenários em tempo real, como atualização factual de preços e dados e obtenção de informações como status de execução do servidor e logs em tempo real. O WebSocket é usado principalmente em cenários de comunicação bidirecional, como bate-papo com várias pessoas, edição colaborativa, etc.
Princípio da SSE
O SSE abre um canal unidirecional entre o servidor e o cliente. O que o servidor responde não é um pacote de dados único, mas um text/event-stream
tipo de informação de fluxo de dados, que é transmitido do servidor para o cliente quando há um fluxo de dados mudar.
Código de back-end do SSE (Nest.js)
Como o projeto é nest.js, aqui está um exemplo escrito com nest.js. O processo de construção da estrutura é omitido e o andaime básico é usado. O código principal do SSE é o seguinte:
- Antes de tudo, o nestjs já encapsula a requisição Sse para nós, só precisamos usar
@Sse
o decorator para preencher a rota correspondente para usá-lo
import {
Controller, Get, Header, Sse } from '@nestjs/common';
import {
AppService } from './app.service';
import {
Observable, interval, map } from 'rxjs';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {
}
@Sse('/sse')
sse(): Observable<any> {
return interval(1000).pipe(map((_) => ({
data:'hello world' } )));
}
}
- Claro, você pode escrevê-lo assim, porque a essência de uma solicitação SSE também é uma solicitação HTTP GET, mas o Content-Type se torna text/event-stream.
@Get('/sse')
@Sse()
@Header('Content-type', 'text/event-stream')
sse(): Observable<any> {
return interval(1000).pipe(map((_) => ({
data: 'hello world2' })));
}
- Os dados que enviamos aqui utilizam o objeto observable (Observable) da biblioteca RxJS, que adota o design do modo observador.Quando o objeto sujeito mudar de estado, ele notificará todos os objetos observadores para que eles se atualizem automaticamente. Observables são preguiçosos e só executam quando são assinados. A
Interval
função da função é enviar um valor em intervalos regulares. Você pode usar outras funções da biblioteca RxJS para enviar o conteúdo. Você só precisa retornar um objeto Observable para realizar a função da interface SSE. - Para obter detalhes sobre esta parte, você mesmo pode consultar a biblioteca RxJS
// 间隔一秒发送数据
return interval(1000).pipe(map((_) => ({
data: 'hello world' })));
// 订阅后推送
const ob$ = new Observable((subscriber) => {
subscriber.next('hello')
subscriber.next('world')
subscriber.complete()
})
return ob$
Código front-end para SSE (React.js)
O front end é escrito em React, e precisamos usar EventSource
a função para implementá-lo. Sua função é abrir uma conexão com uma interface SSE, e então você pode receber os dados dele o tempo todo:
const eventSource = new EventSource("http://localhost:3000/sse");
function Test() {
const [cnt, useCnt] = useState("");
eventSource.onmessage = ({
data }) => {
useCnt(cnt + data);
};
return (
<div>
{
cnt}
</div>
);
}
Dentre eles message
, o evento é disparado quando a informação é recebida, podendo ser disparado das duas formas a seguir
eventSource.addEventListener("message", (event) => {
});
eventSource.onmessage = (event) => {
};
Entre eles open
, o evento é acionado quando a conexão é estabelecida
eventSource.addEventListener("open", (event) => {
});
eventSource.onopen = (event) => {
};
Onde error
o evento é acionado quando ocorre uma exceção
eventSource.addEventListener("error", (event) => {
});
eventSource.onerror = (event) => {
};
Quando saímos da página e não precisamos mais assinar esta interface, podemos usar close
o método para fechar a conexão
eventSource.close();
Geralmente, o que precisamos fazer na cena é conectar ao SSE ao entrar na página, e fechar a conexão ao sair da página, então usamos useEffect para resolver esse problema:
let eventSource: EventSource | null = null;
useEffect(() => {
eventSource = new EventSource("http://localhost:3000/sse");
eventSource.onmessage = ({
data }) => {
console.log(data)
};
return (() => {
eventSource && eventSource.close();
})
},[])
Problemas com SSEs
- Como o SSE depende de conexões persistentes de HTTP, se houver muitas conexões, os recursos do servidor podem ser insuficientes.
- Embora a maioria dos navegadores modernos suporte SSE, ainda existem alguns navegadores mais antigos que não suportam. Ao usar o SSE, verifique se o cliente de destino oferece suporte ao SSE ou fornece um mecanismo alternativo de envio de dados em tempo real.
- O SSE não pode enviar dados binários, apenas texto codificado em UTF-8. Se o aplicativo precisar enviar dados binários, ele precisará usar o Websocket. Portanto, o SSE geralmente é usado para enviar informações de dados para o front-end e não é usado para baixar e transferir arquivos e outros conteúdos.