2017-09-04 61 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,並向該頁面發送包含收集數據的消息。然後,當頁面處理完數據後,它會向工作人員發送一條消息以啓動一個新的請求。因此,我的頁面在請求之間不會有任何不必要的延遲,並且沒有不斷累積的堆棧。如有錯誤,我會終止工作人員並創建一個新的工作人員,以防萬一。