Real-Time Application in NodeJS

最近阅读Mastering Node.js一书,看到第六章,觉得书中的几个例子都特别有代表性,所以自己也事项一遍,顺便做点笔记,以备以后参阅。


AJAX

第一节讲的是AJAX,可能之前比较熟悉吧,或者说,我这一代人可能从来没有接触过那种一个URL,获取HTML文件,里边并不能做什么其它事情的WEB时代。

AJAX主要就是这个A,异步,可以让浏览器在自己想向server获取数据的时候发出请求,并在服务器返回之后做相应的处理,而不用请求整个文档,我目前的理解大致就是这样,不做过多叙述了。

WebSocket

socket的确之前接触的不多,感觉的确很神奇,如何做到实时的通信呢?很是好奇。

不过看过之后,发现其并不是走HTTP协议,所以不是什么黑科技了,而是底层的浏览器所提供的功能,与server之间建立持久的TCP连接,然后相互通信。

书上配套的例子,一个协同画画的东西,很好的展示了websocket的功能,下边就是写的一些说明,备以后查阅。

co-draw

代码:https://github.com/brickmaker/node-real-time-demo/tree/master/co-draw

server

server端的代码非常简单,直接复制过来,因为基本没有特别的与socket.io无关的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const Koa = require('koa');
const app = new Koa();
const serve = require('koa-static');
const server = require('http').createServer(app.callback());
const io = require('socket.io')(server);
app.use(serve(__dirname + '/public'));
io.on('connection', (socket) => {
console.log(`client ${socket.id} connected`)
socket.on('draw', data => {
socket.broadcast.emit('draw', data)
});
});
server.listen(8102);

用了Koa,用koa-static来serve前端文件,Koa和socket.io的接入可能需要记一下,好像并不是那么想当然。

服务端监听客户端的连接,并可以得到客户端的socket,进行后续操作:

1
io.on('connection', socket => {...})

在回调里就可以写一些逻辑了。

client

客户端初始化socket.io很简单:

index.html中加入:

1
<script src="/socket.io/socket.io.js"></script>

然后在scripts中加一条:

1
const socket = io.connect('/');

就OK了,觉得很神奇。

至于操作,这里只用到了两个:

  1. 在自己绘制的时候,向server发消息:“我在绘制…”,并附上绘制的数据
  2. 监听服务器传来别人绘制的消息,然后把别人画的也加上来

OK,基本就是这样。

SSE(Server Sent Events)

顾名思义,就是server向客户端发送消息,不过其实这一点websocket也可以做,这可能也是之前自己从来没有听过这个名词的原因吧。

它的好处可能就是用的是HTTP协议,然后比较简单吧,具体的看Stack Overflow上的两者对比:https://stackoverflow.com/questions/5195452/websockets-vs-server-sent-events-eventsource

Real-time Q&A

唔,写到后边都不太想写了,真的,参考价值不大,其实关于SSE的很少,不过还是要学习一下这种方式。

代码:https://github.com/brickmaker/node-real-time-demo/tree/master/real-time-QA

说白了,就这个例子来看,其实就相当于,建立了一个持久的HTTP连接,然后有数据就写数据,没有什么特别的,只不过都通过那个HTTP发,然后断了之后能重新连上。

server

服务端,拿到客户端请求Event Source时候的socket,存下来,想给谁发数据的时候,直接socket.write()就OK了。

client

客户端的连接也比较简单:

1
const eventSource = new EventSource('/event-source');

然后就是各种addEventListener(...)来监听消息。

值得注意的是,可以设定不同的事件,是通过字符串的方式设定的,比如这样:

1
2
clientSocket.write(`event: ${event}\n`);
clientSocket.write(`data: ${JSON.stringify(data)}\n\n`);

客户端监听对应的事件类别就可以了~