【问题标题】:Comet: XMLHttpRequest.responseText grows endlesslyComet:XMLHttpRequest.responseText 无限增长
【发布时间】:2014-02-22 07:20:01
【问题描述】:

全部,

我正在努力实现一个彗星 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);
}

【问题讨论】:

    标签: javascript comet chunked


    【解决方案1】:

    设置字段无济于事

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

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

    无论您是否访问或设置该属性,都有一个包含(增长的)有效负载的底层增长缓冲区。

    至少在 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 有效负载上可能拥有的其他“视图”,xhr.response(用于 blob)和 xhr.responseXML

    用第二个 XHR 做探戈

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

    Memory efficient message chunk processing using a XMLHttpRequest

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

    multipart/x-mixed-replace

    曾经有一个你可以设置的内容类型,它会指示客户端在收到特定字符串时重置其响应。

    它是为流式传输网络摄像头图像而设计的,在彗星上被滥用了一段时间,并且可以满足您的需求,但至少 Firefox 和 Chrome 放弃了对它的支持。众所周知,它从一开始就不受 IE 的支持,所以今天可能也是如此。

    Content-type: multipart/x-mixed-replace;boundary=<randomstringhere>
    

    &lt;randomstringhere&gt; 不太可能出现在您的应用程序消息中。在服务器发出的每条“推送”消息之间,插入&lt;randomstringhere&gt;。浏览器会自动重置每个边界处的responseText

    这个问题的一个问题是,您必须在浏览器收到下一条消息之前处理边界中的所有消息。所以它很活泼,至少对于 AJAX。

    使用x.response 简化您的生活

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

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

    然而,整个有效载荷仍有可能通过responseText 提供,因此这不足以解决内存失控问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-03
      • 2016-05-28
      • 1970-01-01
      • 2016-08-23
      • 2016-02-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多