SSE 的 EventSource 和 XMLHttpRequest 之间的区别
Difference between EventSource and XMLHttpRequest for SSE
我正在实施服务器发送事件应用程序逻辑。服务器端已经完成,我现在正在处理客户端部分。
无论我在哪里看,JS 都在使用 EventSource Object,这看起来非常合乎逻辑,因为它是为它而生的!但它也有很多限制(只有 GET 请求,没有 headers,没有数据...)
我问自己:为什么不使用 XMLHttpRequest Object 来代替?
我正在访问的服务器是用 Java EE 和 returns 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 层的理解真的很低...
TL;DR: EventSource 处理流事件,每个 "update" 上可以是多条信息。 Ajax 无法开箱即用,实现类似行为可能非常复杂。
您的 XMLHttpRequest
不会是流,因为您只会获得有关 XMLHttpRequest.readyState 更改的数据。
您可以使用XMLHttpRequest advanced features set, where support is a little dodgy (though still better than EventSource中的onprogress
事件获取内容流。
但是您没有办法检测每个进度滴答中的 "new" 数据,因此您将不得不按照 this answer.[=17 中所述发明您自己的更新事件处理=]
即使有了上述答案,您仍然需要一种在一次更新中区分多个事件的方法,因此您必须做一些事情,比如将数据作为 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);
我正在实施服务器发送事件应用程序逻辑。服务器端已经完成,我现在正在处理客户端部分。
无论我在哪里看,JS 都在使用 EventSource Object,这看起来非常合乎逻辑,因为它是为它而生的!但它也有很多限制(只有 GET 请求,没有 headers,没有数据...)
我问自己:为什么不使用 XMLHttpRequest Object 来代替?
我正在访问的服务器是用 Java EE 和 returns 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 层的理解真的很低...
TL;DR: EventSource 处理流事件,每个 "update" 上可以是多条信息。 Ajax 无法开箱即用,实现类似行为可能非常复杂。
您的 XMLHttpRequest
不会是流,因为您只会获得有关 XMLHttpRequest.readyState 更改的数据。
您可以使用XMLHttpRequest advanced features set, where support is a little dodgy (though still better than EventSource中的onprogress
事件获取内容流。
但是您没有办法检测每个进度滴答中的 "new" 数据,因此您将不得不按照 this answer.[=17 中所述发明您自己的更新事件处理=]
即使有了上述答案,您仍然需要一种在一次更新中区分多个事件的方法,因此您必须做一些事情,比如将数据作为 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);