首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >EventSource永久自动重接

EventSource永久自动重接
EN

Stack Overflow用户
提问于 2014-02-17 14:07:28
回答 3查看 9.6K关注 0票数 7

我在项目前端使用JavaScript EventSource。

有时,浏览器和服务器之间的连接失败或服务器崩溃。在这些情况下,EventSource试图在3秒后重新连接,如文档中所述。

但它只试了一次。如果仍然没有连接,则EventSource停止尝试重新连接,用户必须刷新浏览器窗口才能再次连接。

我怎么才能阻止这种行为?我需要EventSource尝试永远重新连接,而不仅仅是一次。

浏览器是Firefox。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-02-18 06:52:57

我通过实现一个“保持生存”的系统来处理这个问题;如果浏览器为我重新连接,这是很好的,但是我认为有时它不能工作,而且不同的浏览器可能会有不同的行为。

我在我的书的第五章中花了几页篇幅(公然的插件,在O‘’Reilly这里找到它:使用HTML5 SSE的数据推送应用程序),但是如果你想要一个非常简单的解决方案,不需要任何后端更改,设置一个全局计时器,在30秒后触发。如果它触发,那么它将杀死EventSource对象并创建另一个对象。拼图的最后一部分是在事件侦听器中:每次从后端获取数据时,杀死定时器并重新创建它。也就是说,只要你至少每30秒得到一次新的数据,计时器就永远不会触发。

下面是一些最起码的代码来说明这一点:

代码语言:javascript
运行
复制
var keepAliveTimer = null;

function gotActivity(){
  if(keepaliveTimer != null)clearTimeout(keepaliveTimer);
  keepaliveTimer = setTimeout(connect, 30 * 1000);
}

function connect(){
  gotActivity();
  var es = new EventSource("/somewhere/");
  es.addEventListener('message', function(e){
    gotActivity();
    },false);
}
...
connect();

还要注意,我在连接之前调用了gotActivity()。否则,如果一个连接失败,或者在它有机会传递任何数据之前就死了,它就会被忽略。

顺便说一句,如果你也能改变后端,在25到30秒的安静之后,发送一条空白消息(“心跳”)是值得的。否则前端就得假设后端已经死了。当然,如果您的服务器发送的定期消息间隔不超过25-30秒,则不需要做任何事情。

如果您的应用程序依赖于Event报头,那么要意识到您的“保持生存”系统必须模拟这个过程;这会涉及到更多的问题。

票数 7
EN

Stack Overflow用户

发布于 2019-01-06 19:18:30

根据我的经验,如果存在网络级错误,浏览器通常会重新连接,但如果服务器使用HTTP错误(例如状态500)进行响应,则不会重新连接。

我们的团队制作了一个简单的包装库,用于在所有情况下重新连接:重新连接-事件源。也许会有帮助。

票数 3
EN

Stack Overflow用户

发布于 2019-01-27 06:08:47

下面,我演示了一种以合理的速度永远重新连接的方法。

这段代码使用了一个uses函数以及重新连接间隔加倍。在我测试的时候,效果很好。它以1秒、4、8、16...up连接,最长64秒,并以相同的速率重新尝试。

代码语言:javascript
运行
复制
function isFunction(functionToCheck) {
  return functionToCheck && {}.toString.call(functionToCheck) === '[object Function]';
}

function debounce(func, wait) {
    var timeout;
    var waitFunc;

    return function() {
        if (isFunction(wait)) {
            waitFunc = wait;
        }
        else {
            waitFunc = function() { return wait };
        }

        var context = this, args = arguments;
        var later = function() {
            timeout = null;
            func.apply(context, args);
        };
        clearTimeout(timeout);
        timeout = setTimeout(later, waitFunc());
    };
}

// reconnectFrequencySeconds doubles every retry
var reconnectFrequencySeconds = 1;
var evtSource;

var reconnectFunc = debounce(function() {
    setupEventSource();
    // Double every attempt to avoid overwhelming server
    reconnectFrequencySeconds *= 2;
    // Max out at ~1 minute as a compromise between user experience and server load
    if (reconnectFrequencySeconds >= 64) {
        reconnectFrequencySeconds = 64;
    }
}, function() { return reconnectFrequencySeconds * 1000 });

function setupEventSource() {
    evtSource = new EventSource(/* URL here */); 
    evtSource.onmessage = function(e) {
      // Handle even here
    };
    evtSource.onopen = function(e) {
      // Reset reconnect frequency upon successful connection
      reconnectFrequencySeconds = 1;
    };
    evtSource.onerror = function(e) {
      evtSource.close();
      reconnectFunc();
    };
}
setupEventSource();
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21831206

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档