Hello,大家好,我是 Sunday。
说到推送数据,大家可能首先想到的是 WebSocket
。
事实上,WebSocket 允许双向通信,自然可以用于服务器到浏览器的消息推送。
然而,如果只需要单向消息推送,HTTP 也可以通过服务器发送事件来实现这一功能。
WebSocket的通信流程如下:
- 首先,通过HTTP切换协议。 服务器返回状态码101后,协议切换成功。
- 然后,WebSocket 格式数据的通信开始,一方可以随时向另一方推送消息。
01:啥是 SSE
对于 HTTP 中服务器发送的事件:
服务器返回的 conteng-type
是 text/event-stream
,这是一个可以多次返回内容的流 。服务器端事件通过这种消息类型随时推送数据。我们把它叫做 SSE
在ChatGPT 中。每次回答问题时,它不会立即给出所有答案,而是逐步加载部分。这也是基于SSE的。
现在我们知道什么是 SSE 及其应用,那么如何实现一个 SSE 呢E
02:实现 SSE
创建一个 nest 项目
js
npx nest new sse-test
运行之后可以看到以下内容:
然后,我们可以在 AppController 中添加一个流(stream)接口。
这里并没有通过@Get、@Post等装饰器来标识,而是通过@Sse
装饰器表明这是一个事件流类型的接口。
js
@Sse('stream')
stream() {
return new Observable((observer) => {
observer.next({ data: { msg: 'aaa'} });
setTimeout(() => {
observer.next({ data: { msg: 'bbb'} });
}, 2000);
setTimeout(() => {
observer.next({ data: { msg: 'ccc'} });
}, 5000);
});
}
它返回的是一个Observable对象,然后内部使用observer.next返回消息。 可以返回任何 JSON 数据。
我们首先返回aaa,2秒后我们返回bbb,5秒后我们返回ccc。
然后创建一个前端页面:创建一个 React 项目。
js
npx create-react-app --template=typescript sse-test-frontend
在App.tsx
中写入以下代码:
js
import { useEffect } from 'react';
function App() {
useEffect(() => {
const eventSource = new EventSource('http://localhost:3000/stream');
eventSource.onmessage = ({ data }) => {
console.log('New message', JSON.parse(data));
};
}, []);
return (
<div>hello</div>
);
}
export default App;
该EventSource是一个本机浏览器API,用于从SSE接口获取响应。 它将把每条消息传递到回调函数 onmessage 中。
我们在 Nest 服务中启用跨域支持。
然后删除react项目的index.tsx文件中的这几行代码,因为它们会导致额外的渲染:
执行 React 项目:npm run start
你可以看到以下内容:
这里的打印,就是服务器发送的事件。
在devtools中,我们可以看到响应的Content-Type是text/event-stream
。
然后在EventStream中,可以看到每条收到的消息。
这样服务器就可以随时向网页推送消息啦!
我们可以在 MDN 上看到它的兼容性列表:
除IE和Edge外,与其他浏览器不存在兼容性问题。
03:SSE 的应用场景
Server-Sent Events
特别适合 只需要服务器端推送的场景。
比如:GPT 项目、日志的实时推送 等
前端训练营:1v1私教,终身辅导计划,帮你拿到满意的
offer
。 已帮助数百位同学拿到了中大厂offer
。欢迎来撩~~~~~~~~