Comet:XMLHttpRequest.responseText无休止地增长

时间:2014-02-22 07:20:01

标签: javascript comet chunked

所有

我正在努力实现一个彗星JS库。现在我正在跟踪响应文本的大小,并在块到达时返回新部分。这为我的回调提供了新数据,但这是一个非常明显的内存泄漏。有没有办法强制关闭XMLHttpRequest对象或定期重置responseText的内容?

request.multi = function(type, handler, url, querystring){
    querystring  = (querystring == undefined) ? null: querystring;

    var response = "";
    var handle   = makeRequestHandle();

    handle.multipart = true;
    handle.open(type, url, true);
    handle.onreadystatechange = function(){
        var return_val;
        if(handle.readyState == 4){
            m_log.debug("Conection died");
        }else if(handle.readyState == 3){
            return_val = handle.responseText.substring(response.length);
            response   = handle.responseText;
            handler(return_val);
        }else{
            m_log.debug("readyState %s", handle.readyState);
        }
    };
    handle.send(querystring);
}

1 个答案:

答案 0 :(得分:0)

设置字段无济于事

你是对的,只要请求处于活动状态,并且你的处理程序使用它,你就会在内存中的某处积累数据。

我说'某处',因为套接字数据会通过几个软件层。只要您的XHR正在进行中,您的运行时(浏览器或js运行时)将继续接收。它必须对内容执行解码(例如(un)gzip),并且可能解码传输编码(如果它是长时间连接,则可能是“chunked”)。

无论您是访问还是设置属性,都有一个包含(增长)有效负载的基础增长缓冲区。

至少在Chrome上,XMLHttpRequest.prototype.responseText仅定义为getter属性。设置它(例如使用xhr.responseText = ''将对底层缓冲区没有影响。内存将继续增长

// you can verify
var xhr = new XMLHttpRequest();
Console.log(Object.getOwnPropertyDescriptor(x.__proto__, "response"))

// I get
{... get: function () {...}, set: undefined }

对于xhr有效载荷{(1}}(对于blob)和xhr.response,您可能拥有的其他“视图”也是如此。

用第二个XHR进行探戈

使连接内存“重置”而不丢失消息的最可靠方法是在旧的ajax请求仍处于活动状态时启动新的ajax请求,并在旧的ajax请求收到完整的最后一条消息后切换到新的ajax请求。虽然两者都处于活动状态,但必须忽略新流上的数据,直到它们处于“同步”状态。

Memory efficient message chunk processing using a XMLHttpRequest

这当然假设流上收到的数据是相同的,或者有一些方法可以唯一地识别进入的消息,使两个流“对齐”。

的multipart / X - 混合替换

曾经有过这样的内容类型,可以指示客户端在收到特定字符串时重置其响应。

它专为流媒体网络摄像头图像而设计,有一段时间被彗星滥用,并且有点像你想要的那样,但它的支持至少从Firefox和Chrome中删除了。众所周知,IE从一开始就不受其支持,所以今天也许如此。

xhr.responseXML

Content-type: multipart/x-mixed-replace;boundary=<randomstringhere> 不太可能出现在您的应用程序消息中。在每个消息“推”服务器之间,您插入<randomstringhere>。浏览器会自动重置每个边界的<randomstringhere>

该问题的一个问题是,在浏览器收到下一个消息之前,您必须处理边界内的所有消息。所以至少对于AJAX来说这很有趣。

使用responseText

简化您的生活

在问题中给出的示例中,responseText用于获取完整的有效负载。在x.response通话之前,可以设置 send(),然后在进程回调中,handle.responseType = "text"将仅包含自上次调用处理程序以来的新信息。

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/response

然而,有可能整个有效载荷仍然可以通过handle.response获得,因此这不足以解决内存失控问题。