2017-09-04 59 views
1

在我的代码(一个监视应用程序)中,我需要定期用链接调用形式的XMLHttpRequest对象调用服务器。每次调用都需要15秒钟,由服务器定时,因为它在该段时间内提供了多个部分结果(HTTP 100 Continue)。紧接完成当前调用后,当前XMLHttpRequest对象的onreadystatechange事件处理程序需要创建并启动下一个请求(使用新实例),因此与服务器的通信几乎是无缝的。避免XMLHttpRequest链调用泄漏

它的工作方式是每次调用都会保留调用者在堆栈中的对象上下文,因此这是一个必须保持打开状态的页面,堆栈不断增长,垃圾收集器无法声明数据。请参阅下面的堆栈跟踪:

Stack trace over a couple of minutes

我不能使用计时器(setInterval的或如)启动下一个请求。它应该从前一个结尾内部启动。来自服务器的数据必须尽快到达,不幸的是,浏览器时下的浏览器在页面没有焦点的时候会出现throtle计时器。正如我所说,这是一个监视应用程序,旨在始终在用户的辅助监视器(很少关注)。我还需要处理HTTP超时和其他类型的错误,这些错误会从15秒序列中退出。应始终只有一个通道与服务器打开。

我的问题是,是否有任何方法来避免在创建XMLHttpRequest对象时将整个上下文保留在堆栈中。即使对DOM对象调用click()方法也会使堆栈/上下文保持活动状态。即使承诺似乎保持上下文。

我也无法使用websockets,因为服务器不支持它们。

UPDATE:

这是比较复杂的,买它在本质上是这样的:

var xhttpObjUrl; 
var xhttpObj; 

onLoad() { 
    loadXMLDoc(pollURL + "first=1", true); 
} 

function loadXMLDoc(url, longtout) { 
    xhttpObjUrl = url; 
    xhttpObj = new XMLHttpRequest(); 
    xhttpObj.open(method, url, true); 
    xhttpObj.onprogress = progress; 
    xhttpObj.onloadend = progress; 
    xhttpObj.ontimeout = progress; 
    if (commlog) consolelog("loadXMLDoc(): url == " + dname); 
    xhttpObj.send(""); 
} 

function progress() { 
    if (!xhttpObj) return; 
    var state = xhttpObj.readyState; 
    var status; 
    var statusText; 
    if (state == 4 /* complete */ || state == 3 /* partial content */) { 
     try { 
      status = xhttpObj.status; 
      statusText = xhttpObj.statusText; 
      if (status == 200) parseServerData(); 
     } catch (err) { 
      status = 500; 
      statusText = err; 
     } 
     if (state == 4 || status != 200) { 
      /* SERVER TERMINATES THE CONNECTION AFTER 15 SECONDS */ 
      /* ERROR HANDLING REMOVED */ 
      var obj = xhttpObj; 
      xhttpObj = undefined; 
      abortRequest(obj); 
      obj = false; 
      RequestEnd(); 
     } 
    } 
} 

function RequestEnd(error) { 
    var now = (new Date).getTime(); 
    var msdiff = now - lastreqstart; 
    var code = function() { loadXMLDoc(pollURL + 'lastpoint=' + evtprev.toString() + '&lastevent=' + evtcurrent.toString()); return false; }; 
    if (msdiff < 1000) addTimedCheck(1, code); /** IGNORE THIS **/ 
    else code(); 
} 
+0

没有代码,答案是“可能” –

+0

添加了代码片段。 –

回答

0

我使用网络工作者解决我的问题。该工作人员将每次结束XMLHttpRequest,并向该页面发送包含收集数据的消息。然后,当页面处理完数据后,它会向工作人员发送一条消息以启动一个新的请求。因此,我的页面在请求之间不会有任何不必要的延迟,并且没有不断累积的堆栈。如有错误,我会终止工作人员并创建一个新的工作人员,以防万一。