【问题标题】:Difference between EventSource and XMLHttpRequest for SSESSE 的 EventSource 和 XMLHttpRequest 之间的区别
【发布时间】:2019-07-31 20:45:22
【问题描述】:

我正在实现一个服务器发送事件应用程序逻辑。服务器端已经完成,我现在正在处理客户端部分。

在我所见的任何地方,JS 都在使用 EventSource 对象,这看起来非常合乎逻辑,因为它是为此而生的!但这也有很多限制(只有 GET 请求,没有标头,没有数据......)

我问自己:为什么不使用 XMLHttpRequest 对象呢?

我正在访问的服务器是用 Java EE 编写的,并返回一个文本/事件流类型的响应。

这是我的实现

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 层的理解真的很低......

【问题讨论】:

  • "EventSource 实例打开到 HTTP 服务器的持久连接,该服务器以 text/event-stream 格式发送事件。连接保持打开状态,直到通过调用 EventSource.close() 关闭。一旦连接打开后,从服务器传入的消息以消息事件的形式传递给你的代码。与WebSockets不同,服务器发送的事件是单向的;即数据消息是单向传递的,从服务器到客户端(例如用户的网络浏览器)” (MDN)
  • 我知道那部分,但它没有回答有关 XMLHttpRequest 的问题

标签: javascript ajax server-sent-events eventsource


【解决方案1】:

TL;DR:EventSource 处理流事件,每个“更新”可以是多条信息。 Ajax 不能开箱即用地处理这个问题,实现类似的行为可能非常复杂。

您的XMLHttpRequest 不会是一个流,因为您只会获得XMLHttpRequest.readyState 更改的数据。

可以使用XMLHttpRequest advanced features 集合中的onprogress 事件获取内容流,其中支持有点狡猾(尽管仍然比EventSource 更好)。

但是,您无法在每个进度滴答中检测什么是“新”数据,因此您必须按照this answer 中的描述发明自己的更新事件处理。

即使有了上述答案,您仍然需要一种在一次更新中区分多个事件的方法,因此您必须执行一些操作,例如将数据作为 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);

【讨论】:

    猜你喜欢
    • 2018-06-10
    • 1970-01-01
    • 2018-03-26
    • 2012-09-17
    • 1970-01-01
    • 2018-03-22
    • 1970-01-01
    • 2021-12-25
    • 2020-05-10
    相关资源
    最近更新 更多