JS SSE 回调不适用于事件侦听器



我正在使用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方法将数据发送到服务器,并使用从服务器接收到的数据填充文本框。在执行post()函数后,我想剪辑clip()文本框中的文本。执行过程必须像这样:

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文件

[EDIT]将callback()移动到'message'处理程序的末尾后,问题仍然存在:

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()操作,默认情况下是异步的。

那么,发生了什么呢:

  1. 用户点击,post()被称为
  2. SSE对象及其事件侦听器已设置
  3. source.stream()被调用,它将请求发送到服务器。
  4. callback()(即clip())称为
  5. 服务器返回响应
  6. 您的message事件处理程序被称为
  7. textArea.value是设置

幸运的是,修复方法很简单:您只希望在收到消息时调用callback()。因此,将callback()移动到message事件处理程序的末尾,而不是post()的末尾。

它将在接收到的每个消息事件之后执行此操作。如果您只希望它在第一个事件之后发生,则需要实现一些逻辑来跟踪已接收的事件数量。(如果只有一个消息事件,您应该使用Ajax调用,而不是SSE/EventSource调用。)

更新:评论中的讨论开始超出了你最初问题的范围(简单地说,答案是"它是异步的,而不是同步的")。但是我认为有必要在这里指出,每次用户单击按钮时都会设置一个新的SSE对象。每个SSE对象都有自己专用的TCP/IP套接字和侦听器函数。这(通常)不是一个好主意:相反,在web应用程序开始时创建SSE连接。

并且,虽然您的SSE多边形库允许使用POST,但标准SSE不允许。如果你只希望应用程序在用户按下按钮时轮询服务器,请考虑从使用SSE切换到使用普通AJAX。

最新更新