LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

【JavaScript】WEB客户端与服务端通讯事件EventSource揭秘

admin
2024年6月15日 10:54 本文热度 755

一、EventSource的基本概念

EventSource是HTML5中的一种新的API,用来实现服务器端向客户端推送事件。相比于常规的轮询方式,EventSource可以实现更加高效、低延迟的数据传输。

它的基本使用方式是,首先在客户端创建一个EventSource对象,然后向指定的服务器端URL发送一个HTTP请求。此时,服务器端需要支持EventStream格式,即Content-Type为text/event-stream。一旦客户端收到了这个请求的响应,它就会开始监听服务器端的事件,并将事件流动态地展现在网页中。

EventSource主要有以下几个特性:

1、实时性。EventSource能够实现实时地数据传输,可以在服务器端有新事件时立即向客户端推送,并自动进行展示。

2、低延迟。由于EventSource采用长连接的方式进行传输,相比于普通的轮询方式,它能够更加高效地传输数据。

3、易用性。EventSource是一种非常易用的API,只需要在客户端创建一个EventSource对象,指定服务器端的URL,即可进行监听并展示事件。

4、兼容性。EventSource能够同时兼容WebSocket和长轮询等方式,具备很好的兼容性,可以在各种不同的场景下使用。

二、EventSource的具体应用场景

EventSource主要用来实现服务器端向客户端实时推送事件,它在Web应用中的应用场景非常广泛。下面列举几个具体的应用场景:

1、即时聊天。在即时聊天应用中,EventSource可以实现实时向客户端推送新消息,从而保证聊天效果的实时性和流畅性。

2、数据监控。在数据监控应用中,EventSource可以实时向客户端推送最新的监控数据,从而让用户及时掌握系统状态。

3、消息提示。在消息提示应用中,EventSource可以实时向客户端推送最新的通知信息,让用户不会错过任何重要消息。

4、广告推送。在广告推送应用中,EventSource可以实时向客户端推送最新的广告信息,从而提高广告的投放效果。

三、EventSource的优缺点

EventSource作为一种新的Web API,具备自身的优缺点:

1、优点

(1)实时展示:EventSource能够实现实时展示服务器端的事件,相比于常规的轮询方式,它能够更加高效、低延迟的展示数据。

(2)易用性:EventSource是一种非常易用的API,只需要在客户端创建一个EventSource对象,指定服务器端的URL,即可进行监听并展示事件。

(3)兼容性良好:EventSource能够同时兼容WebSocket和长轮询等方式,具备很好的兼容性,可以在各种不同的场景下使用。

(4)网络带宽节省:EventSource采用长连接的方式进行数据传输,相比于普通的轮询方式,能够节省大量的网络带宽。

2、缺点

(1)一次性消息:EventSource只能一次性地向客户端推送一条消息,而不能像WebSocket那样实现双向通讯。

(2)不支持二进制数据传输:EventSource只能传输文本数据,不能传输二进制数据,这在某些场景下可能存在一定的局限性。

(3)不支持重连:如果网络连接不稳定,或者服务器端关闭EventStream连接,客户端需要重新连接才能继续监听事件。

四、如何使用EventSource

使用EventSource也比较简单,只需要创建一个EventSource对象并指定服务器端的URL即可。下面是一个简单的使用示例:

var eventSource = new EventSource("/events");

eventSource.onmessage = function(event) {

  console.log("Received event: " + event.data);

};

在这个示例中,创建了一个EventSource对象,并指定服务器端的URL为"/events"。同时,还注册了一个onmessage事件回调函数,在每次收到服务器端推送的事件时,会打印出事件数据。

在服务器端,需要确保能够接收和处理EventStream格式的HTTP请求。下面是一个简单的Node.js的Express应用示例:

const express = require('express');

const app = express();


app.get('/events', function(req, res) {

  res.set({

    'Content-Type': 'text/event-stream',

    'Cache-Control': 'no-cache',

    'Connection': 'keep-alive'

  });


  setInterval(function() {

    res.write('data: ' + new Date().toISOString() + '\n\n');

  }, 1000);

});


app.listen(3000, function() {

  console.log('Example app listening on port 3000!');

});

在这个示例中,创建了一个Express应用,并通过路由"/events"来处理EventSource请求。其中,将响应的Content-Type设置为text/event-stream,表示返回的数据格式为EventStream。同时,通过设置Cache-Control和Connection实现长连接的功能。在每秒钟向客户端推送一个带时间戳的事件。

五、总结

本文主要介绍了EventSource的基本概念、具体应用场景、优缺点以及使用方法。尽管EventSource在某些场景下可能存在一定的局限性,但它仍然是一种非常强大的前端Web API,能够实现实时、低延迟的数据传输,具备很好的兼容性和易用性。在实际应用中,需要针对具体的场景进行合理使用,从而发挥最大的效果。


该文章在 2024/6/15 11:42:55 编辑过

全部评论1

admin
2024年6月15日 10:55

服务端推

服务端推,指的是由服务器主动的向客户端发送消息(响应)。在应用层的HTTP协议实现中,“请求-响应”是一个round trip,它的起点来自客户端,因此在应用层之上无法实现简易的服务端推功能。当前解决服务端推送的方案有这几个:

1、客户端长轮询

2、websocket双向连

3、iframe永久帧

长轮训虽然可以避免短轮训造成的服务端过载,但在服务端返回数据后仍需要客户端主动发起下一个长轮训请求,等待服务端响应,这样仍需要底层的连接建立而且服务端处理逻辑需要相应处理,不符合逻辑上的流程简单的服务端推送;

websocket连接相对而言功能最强大,但是它对服务器的版本有要求,在可以使用websocket协议的服务器上尽量采用此种方式;

iframe永久帧则是在在页面嵌入一个专用来接受数据的iframe页面,该页面由服务器输出相关信息,如,服务器不停的向iframe中写入类似的script标签和数据,实现另一种形式的服务端推送。不过永久帧的技术会导致主页面的加载条始终处于“loading”状态,体验很差。

HTML5规范中提供了服务端事件EventSource,浏览器在实现了该规范的前提下创建一个EventSource连接后,便可收到服务端的发送的消息,这些消息需要遵循一定的格式,对于前端开发人员而言,只需在浏览器中侦听对应的事件皆可。

相比较上文中提到的3中实现方式,EventSource流的实现方式对客户端开发人员而言非常简单,兼容性上出了IE系的浏览器(IE、Edge)外其他都良好;对于服务端,它可以兼容老的浏览器,无需upgrade为其他协议,在简单的服务端推送的场景下可以满足需求。在浏览器与服务端需要强交互的场景下,websocket仍是不二的选择。

EventSource规范简析

浏览器端

浏览器端,需要创建一个EventSource对象,并且传入一个服务端的接口URI作为参数。

var evtSource = new EventSource('http://localhost:9111/es');

其中,'http://localhost:9111/es'为服务端吐出数据的接口。目前,EventSource在大多数浏览器端不支持 跨域,因此它不是一种跨域的解决方案。

默认EventSource对象通过侦听“message”事件获取服务端传来的消息,“open”事件则在http连接建立后触发,”error“事件会在通信错误(连接中断、服务端返回数据失败)的情况下触发。同时,EventSource规范允许服务端指定自定义事件,客户端侦听该事件即可。

evtSource.addEventListener('message',function(e){

    console.log(e.data);

});

evtSource.addEventListener('error',function(e){

    console.log(e);

})

服务端

事件流的对应MIME格式为text/event-stream,而且其基于HTTP长连接。针对HTTP1.1规范默认采用长连接,针对HTTP1.0的服务器需要特殊设置。

服务端返回数据需要特殊的格式,它分为四种消息类型:

event, data, id, retry

其中,event指定自定义消息的名称,如event: customMessage\n;

data指定具体的消息体,可以是对象或者字符串,如data: JSON.stringify(jsonObj)\n\n,在消息体后面有两个换行符\n,代表当前消息体发送完毕,一个换行符标识当前消息并未结束,浏览器需要等待后面数据的到来后再触发事件;

id为当前消息的标识符,可以不设置。一旦设置则在浏览器端的eventSource对象中就会有体现(假设服务端返回id: 369\n),eventSource.lastEventId == 369。该字段使用场景不大;

retry设置当前http连接失败后,重新连接的间隔。EventSource规范规定,客户端在http连接失败后默认进行重新连接,重连间隔为3s,通过设置retry字段可指定重连间隔;

每个字段都有名称,紧接着有个”:“。当出现一个没有名称的字段而只有”:“时,这就会被服务端理解为”注释“,并不会被发送至浏览器端,如: commision

由于EventSource是基于HTTP连接之上的,因此在一段没有数据的时期会出现超时问题。服务器默认HTTP超时时间为2分钟,在node端可以通过response.connection.setTimeou(0)设置为默认的2min超时, 因此需要服务端做心跳保活,否则客户端在连接超时的情况下出现net::ERR_INCOMPLETE_CHUNKED_ENCODING错误。通过阅读相关规范,发现注释行可以用来防止连接超时,服务器可以定期发送一条消息注释行,以保持连接不断。

下面提供koa的服务端代码:

var fs = require('fs');

var path = require('path');

var PassThrough = require('stream').PassThrough;

var Readable = require('stream').Readable;

var koa = require('koa');

var Router = require('koa-router');

var app = new koa();

var router = new Router();


function RR(){

    Readable.call(this,arguments);

}

RR.prototype = new Readable();

RR.prototype._read = function(data){

}


router.get('/',function(ctx,next){

    ctx.set('content-type','text/html');

    ctx.body = fs.readFileSync(path.join(process.cwd(),'eventServer.html'));

});


const sse = (stream,event, data) => {

    return stream.push(`event:${ event }\ndata: ${ JSON.stringify(data) }\n\n`)

//    return stream.write(`event:${ event }\ndata: ${ JSON.stringify(data) }\n\n`);

}

router.get('/es',function(ctx,next){

    var stream = new RR()//PassThrough();

    ctx.set({

        'Content-Type':'text/event-stream',

        'Cache-Control':'no-cache',

        Connection: 'keep-alive'

    });

    sse(stream,'test',{a: "yango",b: "tango"});

    ctx.body = stream;

    setInterval(()=>{

        sse(stream,'test',{a: "yango",b: Date.now()});

    },3000); 

});


app.use(router.routes());

app.listen(9111,function(){

    console.log('listening port 9111');

});

此处需要注意的是koa-router的返回值必须是一个Stream(Readable),这是由于koa的特殊性造成的。如果context.body不是Stream是一个字符串或者Buffer实例,会直接在node原生中调用res.end(buffer),结束了HTTP响应:

koa lib/application.js


// responses

if (Buffer.isBuffer(body)) return res.end(body);

if ('string' == typeof body) return res.end(body);

if (body instanceof Stream) return body.pipe(res);

因此造成了服务端事件流无法正确响应。而返回Stream类型的方式有几种,如通过扩展stream模块的Readable可读流返回或者直接采用PassThrough流返回,亦可通过through2模块或者Transform对象实现,归根到底保证可以从该stream对象中pipe出数据至http.ServerResponse对象中。

附页面代码

<!DOCTYPE html>

<html>

<head>

</head>

<body>

    <div>

        hello world

    </div>

    <p id="info"></p>

    <script>

        var infoShow = document.querySelector('#info');

        var se = new EventSource('http://localhost:9111/es');

        se.addEventListener('test',function(e){

            infoShow.textContent += e.data+'\n';

        });

        se.addEventListener('error',function(e){

            console.log(e);

        })

    </script>

</body>

</html>

参考资料

使用服务器发送事件 EventSource超时


该评论在 2024/6/15 11:50:39 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved