如果不活动,Firefox会随机关闭XMLHttpRequest连接。 为什么?

在JavaScript类中,XMLHttpRequest连接到服务器。 服务器正在缓慢发送数据。 这项工作在Chromium中很好,但Firefox在随机时间之后关闭连接(在〜4s和〜70s之间)。

为什么Firefox关闭连接? 以及如何避免这种情况?

简化的JS代码:

    var options = {};
    options['header']=
        { 'Cache-Control':'no-cache, max-age=0', 
            'Content-type': 'application/octet-stream',
            'Content-Disposition': 'inline'
        };

    // Get request information
    this.http = new XMLHttpRequest();
    this.http.onreadystatechange = _streamingResponse.bind(this);
    this.http.open('post', url, true);
    for (var i in options['header'])
    {
        this.http.setRequestHeader(i, options['header'][i]);
    }
    this.http.send('');

对于PHP部分,如下所示:

sleep(200); //wait long time, so firefox close the socket.

如果服务器每隔几秒发送一次(<5s),则连接将永久保持活动状态。 但是如果没有数据发送,Firefox关闭连接。

连接关闭: - readyState = 4 - status = 0

服务器似乎是正确的,因为在Chromium中它正常工作。

完整的测试代码:

的test.html

<html>
<header>
</header>
<body>
</body>

<script type="application/javascript">

    function log( msg )
    {
        document.body.appendChild(document.createElement('div').appendChild(document.createTextNode(msg)));
        document.body.appendChild(document.createElement('br'));
    }

    function request(url)
    {
        function _streamingResponse()
        {
            if (4==this.http.readyState)
            {
                log('Done: ' + this.http.status);
            }
            else if (3==this.http.readyState)
            {
                var text = this.http.response.substr(this.lastRequestPos);
                this.lastRequestPos = this.http.response.length;
                log('Update: ' + text);
            }
        }

        var options = {};
        options['header']=
            { 'Cache-Control':'no-cache, max-age=0', 
                'Content-type': 'application/octet-stream',
                'Content-Disposition': 'inline'
            };

        this.lastRequestPos=0;

        // Get request information
        this.http = new XMLHttpRequest();
        this.http.onreadystatechange = _streamingResponse.bind(this);
        this.http.open('post', url, true);
        for (var i in options['header'])
        {
            this.http.setRequestHeader(i, options['header'][i]);
        }
        this.http.send('');
        log('Request sent!');
    }

    req = new request('./test.php');
</script>
</html>

test.php的

<?php

$timer = 60;

ignore_user_abort(true);
set_time_limit(0);

// Turn off output buffering and compression
ini_set('output_buffering', 'off');
ini_set('zlib.output_compression', false);
ini_set('implicit_flush', true);
ob_implicit_flush(true);
while (ob_get_level() > 0) {
    $level = ob_get_level();
    ob_end_clean();
    if (ob_get_level() == $level) break;
}
if (function_exists('apache_setenv')) {
    apache_setenv('no-gzip', '1');
    apache_setenv('dont-vary', '1');
}

// Set header for streaming
header('Content-type: application/octet-stream');
flush();

// Send information
sleep($timer);
echo '<yes></yes>';
flush();

?>

其他说明:Firefox 43.0.03,Chromium 47.0.2526

编辑:

设置一个回叫超时它不会触发。 我认为这不是暂停。

this.http.timeout = 2000;
this.http.ontimeout = _streamingTimeout.bind(this);

进一步搜索后,我发现Mozilla中的一个Bug似乎是这种行为的责任。 它应该在45版本中得到解决,但在那之前,我们必须带领它。

即使这个错误似乎只与Ipv6相关,我也有使用127.0.0.1的相同问题。 但是,使用Firefox Developer Edition(V 45),问题似乎已解决。

为什么Firefox关闭连接?

它不应该。 ref:https://bugzilla.mozilla.org/show_bug.cgi?id = 1240319

如何解决它?

除了每3-4秒发送一次数据以保持连接打开,我不知道。


听起来很像垃圾回收。

我看你已经试过超时。 但我不确定我是否理解你的结论:设置超时回调不触发。

只要确保遵守以下规则:

4.2垃圾收集

如果XMLHttpRequest对象的状态是使用send()标志设置,收到的头或加载打开的, 并且它有一个或多个注册的事件侦听器,其类型是readystatechange,progress,abort,error,加载,超时和加载。

如果XMLHttpRequest对象在其连接仍处于打开状态时进行垃圾回收,则用户代理必须终止该请求。

xhr.spec.whatwg.org

检查哪些状态,send()标志和事件监听器是否设置,而没有数据发送。

链接地址: http://www.djcxy.com/p/89687.html

上一篇: Firefox randomly close XMLHttpRequest connection if inactive. Why?

下一篇: Comparing the modules in Python. OK, but why?