在Firefox浏览器中,EventSource监听器在页面加载时不会触发

3
我有点困惑,为什么在其他(所有)浏览器中可以工作,但在Firefox中无法工作。
初始化EventSource并注册监听器:
var output = new EventSource('/subscribe');

output.addEventListener('shell_stream', function(e) {
    $('#shell-output').append(e.data + "<br/>");
}, false);

当页面加载时,我查看查询字符串,如果有文件并运行操作,则通过ajax将它们发送到服务器,并且服务器将数据发送回上面注册的监听器。

已经对脚本进行了调试。 它确实发送请求并接收有效响应,而服务器肯定会向侦听器发送数据。

然而,在Firefox上,监听器没有任何反应。

值得注意的是,如果用户单击“运行”按钮,它将调用在查询字符串中找到文件和运行时调用的完全相同的函数,侦听器将完美地工作。

此外,如果我在页面加载时触发alert()并且用户点击它,则侦听器将起作用!

这里是尝试各种浏览器的实时链接:

http://cibox.org/slivu/stackoverflow?file=extract-image.rb&run=true

谢谢。


你的服务器是否可能在EventSource HTTP请求连接到服务器之前尝试向EventSource发送数据?代码编写方式看起来像是EventSource和随后立即触发的XHR会竞争,但这实际上取决于服务器在收到该XHR时所做的确切操作。 - Boris Zbarsky
不,我也有同样的想法。它肯定是在连接后才发送请求。 - user904990
好的,我刚刚跟踪了一下。当页面加载时,浏览器在事件源上获取了一个136字节的HTTP连接响应。响应有两个rpc_stream事件:进度条的显示和隐藏。当我单击“运行”按钮时,我会得到另一个显示进度条的事件,然后是一个大小为216字节的块,其中包含几个shell_stream事件,然后是另一个rpc_stream来隐藏进度条。因此,看起来在最初的加载时,服务器只是没有发送shell_stream事件... - Boris Zbarsky
好的,那么它在其他浏览器中是如何工作的呢?另外,为什么如果我在加载时执行一个简单的 alert('something'); 并且用户点击它,流将在不点击“运行”按钮的情况下工作。这与用户交互有关,例如只有在用户以某种方式与页面交互后,流才会起作用。 - user904990
我最好的猜测是你仍然有一个竞争条件,这可能会导致你的服务器根据接收请求的顺序发送错误的内容。这也是其他浏览器可以正常工作的方式,以及如果某些事件的时间发生变化(alert()就是其中之一)。你可以尝试通过在setTimeout中执行任何加载工作来测试这个理论... - Boris Zbarsky
@BorisZbarsky 这很有道理,马上尝试。 - user904990
1个回答

2

最终更新

将此内容移至单独的帖子中:

https://stackoverflow.com/questions/13159977


=== 更新 ===

忘记/错过了每N秒调用一次onopen :)

所以我的文件一直在运行 :)

现在先使用一个丑陋的hack:

initialized = false;
var output = new EventSource( ... );

output.onopen = function() {
  if(initialized) return true;
  initialized = true;

  ...
  invoke_file_runner( ... );
}

initialized 确保它只运行一次。


找到了!

我的代码看起来像这样:

var output = new EventSource( ... );
...
invoke_file_runner( ... );

有趣的是,在所有浏览器上,当执行invoke_file_runner时,连接已经建立。

除了Firefox,那里的连接是之后建立的。

不知道原因和原理。

修复很简单:

var output = new EventSource( ... );
output.onopen = function() {
  ...
  invoke_file_runner( ... );
}

这将确保只有在连接建立后才执行invoke_file_runner

哈哈,看起来我可以接受自己的答案,但我的积分在哪里呢? :) - user904990
另外,您可以使用 once 事件监听器。output.addEventListener("open", /*func*/, { once: true})。https://www.youtube.com/watch?v=pwLkdksiClE - yzorg

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