SSE的EventSource和XMLHttpRequest有什么区别?

3
我正在实现一个服务器发送事件应用程序逻辑。服务器端已经完成,现在我正在处理客户端部分。
无论我看哪里,JS都使用EventSource对象,这似乎非常合理,因为它是为此而设计的!但它也有很多限制(只能使用GET请求,没有标头,没有数据...)
我问自己:为什么不改用XMLHttpRequest对象呢?
我访问的服务器是用Java EE编写的,并返回一个text/event-stream类型的响应。
以下是我的实现。
var source = new EventSource("my_url");
source.onmessage = function (event) {
  console.log(event.data);
};

var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
  if (xhttp.readyState == 3) {
    console.log(xhttp.response);
  }
};
xhttp.open("GET", "my_url", true);
xhttp.send();

两种方法都可以正常工作,但由于我在这个主题上没有找到任何信息,所以我想知道是否有什么可怕的事情正在发生。

唯一看到的区别是,在Ajax中,响应是将一个接一个地连接在一起的。 我推断服务器缓冲区没有被刷新,但我对所有这些HTTP层的理解非常低......


1
一个 EventSource 实例会打开一个与 HTTP 服务器的持久连接,服务器以 text/event-stream 格式发送事件。该连接会一直保持打开状态,直到调用 EventSource.close() 进行关闭。连接建立后,来自服务器的传入消息将以消息事件的形式传递给您的代码。与 WebSockets 不同,服务器推送的事件是单向的,也就是说,数据消息是从服务器单向传递到客户端(例如用户的 Web 浏览器)。 - Andreas
3
我知道那一部分,但它并没有回答关于XMLHttpRequest的问题。 - Florent Descroix
1个回答

4
TL;DR: EventSource 处理流式事件,每个“更新”可能包含多个信息。Ajax 不能直接处理此类情况,实现类似行为可能会非常复杂。
你的 XMLHttpRequest 不是一个流,因为只有在 XMLHttpRequest.readyState 更改时才会收到数据。
你可以使用 XMLHttpRequest 高级特性 中的 onprogress 事件获取内容流,但其支持度不太可靠(尽管仍优于 EventSource)。
但是,您无法检测每个进度标记中的新数据,因此必须像 这个答案中所述那样发明自己的更新事件处理方法。
即使有了上述答案,您仍然需要一种区分一个更新中的多个事件的方法,因此必须像将数据作为 JSON 字符串发送、解析它们并进行自己的事件处理那样做。
所有上述问题都已由 EventSource 处理,这就是为什么人们使用它的原因。
下面是伪代码:
XHR 事件流的实现大致如下:
JavaScript
function Stream(updateCallback) {
    //last response length
    var last_response_len = 0;
    //Create XHR object
    var xhttp = new XMLHttpRequest();
    //Add eventlistener
    xhttp.onprogress = function () {
        //Get new part of response
        var responseText = xhttp.response.substr(last_response_len);
        //Set new response position
        last_response_len = xhttp.response.length;
        //Split into individual events, using a safe seperator which won't naturally occur in your events
        responseText.split("▼")
            //Only keep non-empty events to prevent JSON.parse error
            .filter(function (l) { return l.length > 0; })
            //Loop through events
            .forEach(function (text) {
            //Parse JSON to functional objects
            var data = JSON.parse(text);
            //Do something with each data element
            for (var key in data) {
                //Ignore potential prototype keys
                if (data.hasOwnProperty(key)) {
                    //Do event handling of some sort
                    updateCallback(data[key], key);
                }
            }
        });
    };
    //Initialize request
    xhttp.open("POST", "./", true);
    //Send Request
    xhttp.send();
}
// # TEST # //
//Output elements
var header = document.body.appendChild(document.createElement("h1"));
var values = document.body.appendChild(document.createElement("h2"));
//Event handling function
function OnUpdate(value, key) {
    if (key == 'header') {
        header.innerHTML = value;
    }
    if (key == 'value') {
        values.innerHTML = value;
    }
}
//Start stream
Stream(OnUpdate);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接