javascript - JS SSE 回调不适用于 EventListener
问题描述
我正在使用 JS 库在我的 html 页面上流式传输服务器发送的事件:
<html>
<textarea rows='14' id="value" placeholder="anything you want here"></textarea>
<button type="button" onclick="post(clip)">get</button>
</html>
<script type="text/javascript" src="sse.js"></script>
<script>
url = "http://ac6ba97b046a5dcc677e.elb.us-east-1.amazonaws.com/myapi";
let textArea = document.getElementById("value");
function clip(){
s = textArea.value;
s = s.slice(0, -5);
textArea.value = s;
console.log('hello');
}
function post(callback){
var v = String(textArea.value);
console.log(v);
var source = new SSE(url, {
method: 'POST',
headers: { 'Content-Type': 'text/plain' },
payload: v
});
var arr = [];
source.addEventListener('message', function (e) {
arr.push(e.data);
textArea.value = arr.map(el => el || " ").join('');
});
source.stream();
callback();
}
</script>
单击按钮时,使用 POST 方法将数据发送到服务器,并使用从服务器接收到的数据填充文本框。我想在函数执行clip()
后剪辑文本框中的文本。post()
执行过程必须是这样的:
1. post() logs textArea value
2. source.stream() is executed, textbox populated
3. clip() clips last 5 characters and logs 'hello'
但我反而得到了这个:
1. post() logs textArea value
2. clip() clips last 5 characters and logs 'hello'
3. source.stream() is executed, textbox populated
出于某种原因,甚至在添加回调之后clip()
才被执行。source.stream()
我正在使用的sse.js文件。
[编辑] 移动callback()
到“消息”处理程序的末尾后,问题仍然存在:
function post(callback){
var v = String(textArea.value);
console.log(v);
var source = new SSE(url, {
method: 'POST',
headers: { 'Content-Type': 'text/plain' },
payload: v
});
var arr = [];
source.addEventListener('message', function (e) {
arr.push(e.data);
textArea.value = arr.map(el => el || " ").join('');
callback();
});
source.stream();
}
有谁知道这可能是什么原因造成的?
解决方案
当您的脚本调用source.stream();
时,它正在执行一个XMLHttpRequest.send()
操作,默认情况下是异步的。
那么,发生了什么:
- 用户点击,并被
post()
调用 - SSE 对象及其事件侦听器已设置
- source.stream() 被调用,它将请求发送到服务器。
callback()
(即clip()
)被称为- 服务器发回响应
- 您的
message
事件处理程序被调用 textArea.value
已设置
幸运的是,修复很简单:您只想callback()
在收到消息时被调用。所以将 callback() 移动到message
事件处理程序的末尾,而不是post()
.
它会在收到每个消息事件后执行此操作。如果您只希望它在第一个事件之后发生,您将需要实现一些逻辑来跟踪已收到多少事件。(如果只有一个消息事件,您应该使用 Ajax 调用,而不是 SSE/EventSource 调用。)
更新:评论中的讨论开始超出您原始问题的范围(简单地说,答案是“它是异步的,而不是同步的”)。但我认为值得在这里指出的是,每次用户单击按钮时,您都会设置一个新的 SSE 对象。每个 SSE 对象都有自己的专用 TCP/IP 套接字和自己的侦听器功能。这(通常)不是一个好主意:而是在您的 Web 应用程序启动时创建一次 SSE 连接。
而且,尽管您的SSE
polyfill 库允许使用 POST,但标准 SSE 不允许使用. 如果您只希望应用程序在用户按下按钮时轮询服务器,请考虑从使用 SSE 切换到普通 AJAX。
推荐阅读
- sentiment-analysis - 为什么在我们的 LUIS 应用中关闭了情绪分析?
- python - Python如何将数据插入MySQL
- azure-active-directory - 用于在 Azure AD 中创建组的图形 API 权限
- sas - 样本量小且不同的逻辑回归
- html - 在角度模板中使用来自异步操作的变量
- java - 比较 Java 中的两个 Spark Schema,无法转换 Seq
列出 - mysql - 连接 2 个表 (a, b) 并返回 (b) 中为 NULL 的值
- kivy - 如何在该小部件的根类之外引用宽泛的 id?
- r - 什么是 R 函数唯一和聚合的 Stata 等价物?
- python - 如何将未知数据转换为能够在模型上进行预测?