node koa
When you want to have real time updates on a web application, you can rely on old-fashioned periodic polling or try to use some push capable modern technology. Your first impulse may be using WebSockets. However, if you just want to receive data from the server you can use Server Sent Events.
当您想在Web应用程序上进行实时更新时,可以依靠老式的定期轮询,也可以尝试使用一些具有推送功能的现代技术。 您的第一个冲动可能是使用WebSockets 。 但是,如果您只想从服务器接收数据,则可以使用Server Sent Events 。
Traditionally, a web page has to send a request to the server to receive new data; that is, the page requests data from the server. With server-sent events, it’s possible for a server to send new data to a web page at any time, by pushing messages to the web page. These incoming messages can be treated as Events + data inside the web page.
传统上,网页必须向服务器发送请求以接收新数据。 也就是说,页面从服务器请求数据。 使用服务器发送的事件 ,服务器可以通过将消息推送到网页来随时将新数据发送到网页。 这些传入消息可被视为网页内的事件+数据。
You can check this post to see the difference between SSE and Websocket and make your own opinion of when to use one or the other. For my use case, receiving updates from the server periodically, I will stick to SSE.
您可以查看这篇文章,以了解SSE和Websocket之间的区别,并对何时使用其中一种发表自己的见解。 对于我的用例,定期接收来自服务器的更新,我将坚持使用SSE。
Koa的SSE基础 (SSE basics with Koa)
Let’s start by building a Koa based HTTP server.
让我们从构建基于Koa的HTTP服务器开始。
- It will have a catch all route that responds with a 200 status. 它将捕获一条响应为200状态的所有路由。
It will have a
/sse
endpoint that, upon receiving a request, will make sure our connection stays open by adjusting some socket params and return the appropriate HTTP headers to start a new SSE stream.它将具有一个
/sse
端点,该端点在收到请求后将通过调整一些套接字参数并返回适当的HTTP标头以启动新的SSE流来确保我们的连接保持打开状态。We will create a new PassThrough stream (a stream that simply passes the input bytes across to the output) and pass it as our response body.
我们将创建一个新的PassThrough流(将输入字节简单地传递到输出的流),并将其作为响应主体传递。
- Lastly we will generate a data feed using a simple interval that will periodically write the current timestamp to the stream; therefore, pushing that data across the open connection to the client. 最后,我们将使用一个简单的间隔生成一个数据提要,该间隔将定期将当前时间戳记写入流; 因此,将数据通过打开的连接推送到客户端。
Notice two things: first, the output data must conform to the SSE format. Second it’s mandatory to return a stream as the body response to ensure that Koa does not close the connection. You can dig in the Koa source code (check this method) to see how Koa handles the response. If you take a look you’ll see that Koa will send the body content to the HTTP response stream unless you use another stream as the body. In that case it will pipe the streams; therefore, the response stream won’t be closed until we close our PassThrough stream.
请注意两件事:首先,输出数据必须符合SSE格式 。 其次,必须返回流作为正文响应,以确保Koa不关闭连接。 您可以挖掘Koa源代码(选中此方法 )以查看Koa如何处理响应。 如果您看一下,会发现Koa会将正文内容发送到HTTP响应流,除非您使用其他流作为正文。 在这种情况下,它将通过管道传输流; 因此,在我们关闭PassThrough流之前,不会关闭响应流。
To test our SSE stream in the browser we should use the EventSource API.
要在浏览器中测试我们的SSE流,我们应该使用EventSource API 。
Visit http://localhost:8080
in your browser, open a console and drop the following snippet to consume the server messages.
在浏览器中访问http://localhost:8080
,打开控制台并删除以下片段以使用服务器消息。
关闭流 (Closing the stream)
If you reload your browser or close your source (using the close()
method) your server will break. The interval will try to write on the stream, and… it’s gone!
如果重新加载浏览器或关闭源(使用close()
方法),则服务器将中断。 间隔将尝试在流上写入,并且……已经消失了!
We have to be careful when dealing with closures, in this case our stream. Our interval does not know that it has to stop feeding data to the stream.
在处理闭包(在本例中为流)时,我们必须小心。 我们的间隔不知道它必须停止向流中馈送数据。
To solve it, we can attach ourselves to the stream close
event and “unsubscribe” from the data feed.
为了解决这个问题,我们可以将自己附加到流 close
事件上,并从数据提要中“取消订阅”。
广播数据 (Broadcasting data)
The previous examples generate a new data feed for each connected client. In real world scenarios we also want to broadcast the same data to different clients.
前面的示例为每个连接的客户端生成一个新的数据提要。 在现实世界中,我们还希望将相同的数据广播到不同的客户端。
We can add a simple EventEmitter and move the data generation outside of the connection code to see how this could work.
我们可以添加一个简单的EventEmitter并将数据生成移到连接代码之外,以查看其工作方式。
格式化流数据 (Formatting the stream data)
As I mentioned before the SSE stream data must conform to a standarized format. To ease the pain of translating from data objects to SSE messages we will swap our PassThrough stream with a custom stream Transformer.
如前所述,SSE流数据必须符合标准格式。 为了减轻从数据对象转换为SSE消息的痛苦,我们将PassThrough流与自定义流Transformer交换。
- The transformer (line 5) will convert objects into SSE text format.To simplify the example, we will just handle data only messages (line 13). 转换器(第5行)会将对象转换为SSE文本格式。为简化示例,我们仅处理数据消息(第13行)。
Our data feed will emit a data object with a
timestamp
key (line 22).我们的数据Feed将发出带有
timestamp
键的数据对象(第22行)。- Our event listeners will write the raw data to the transformer (line 46). 我们的事件侦听器会将原始数据写入转换器(第46行)。
We also have to make a minor adjustment to our client to process the new JSON formatted data.
我们还必须对客户端进行较小的调整,以处理新的JSON格式的数据。
加起来 (Summing up)
This is just a barebones example to illustrate the SSE technology: how easy is to use it in Node and how you have to use streams to build SSE into a Koa service. You can extend the example’s SSEStream to support all the Event Stream format and much more.
这只是一个简单的例子来说明SSE技术:在Node中使用它多么容易,以及如何使用流将SSE内置到Koa服务中。 您可以扩展示例的SSEStream以支持所有事件流格式以及更多其他格式 。
As I mentioned at the beginning of this story, when dealing with server to client unidirectional communication you can choose between websockets and Server Sent Events. Each one has pros and cons. Learn both of them and choose the one that fits your problem.
正如我在本故事开始时提到的那样,在处理服务器到客户端的单向通信时,可以在websocket和服务器发送事件之间进行选择。 每个人都有优点和缺点。 了解它们两者,然后选择适合您的问题的一种。
翻译自: https://medium.com/trabe/server-sent-events-sse-streams-with-node-and-koa-d9330677f0bf
node koa