2013-04-30 58 views
1

這可能是一個新問題,但.... 最近,我一直在使用window.setTimeout對父函數進行遞歸調用,對服務器進行ajax輪詢。在這種情況下使用window.setTimeout()和window.setInterval()

function connectToVM(portal) { 
    //making the ajax call here.... 
    if(response.responseText !== "") 
    { 
    windowInterval = window.setTimeout(function() { 
     connectToVM(portal) 
    } 
    , 4000); 
    } 
    } 

windowInterval這裏是我的全局變量。

if(!checkIfChartExists()) { 
    window.clearInterval(windowInterval); 
} 

現在,而不是利用的變量在這裏,我知道我可以簡單的通過了functionclearTimeout,但也導致其他所有的時間間隔要停止:(

我之所以我這樣做是服務器超時,只有當有迴應 我的情況是,我有一個圖表,它更新每個超時間隔 AFAIK,當我們設置間隔時,有一個特定的值設置爲變量(如果設置爲一個變量),所以當我打印我的變量時(每次調用超時函數時),我都會得到一些獨特的int值。

我有很多選項卡,並且許多選項卡可以具有相同的圖表..它只是使用以前觸發的相同間隔。 現在我只有1個圖表。但我有很多圖表來顯示哪些是相同類型。說量表圖表。

我也必須在當前選定的選項卡中沒有圖表時清除超時 - 我正在做這些。 所以我打算只做1個函數,它只是通過將所需的參數傳遞給此函數來調用服務器。

但是爲了輪詢,我使用了上面提到的window.setTimeout。 這適用於1圖表。 現在,我嘗試添加另外1個圖表,使用不同的參數集來輪詢服務器,我將需要使用一些不同於先前觸發的超時值的不同setTimeout函數。

我還必須考慮如果第一個圖表已經存在,超時已經被觸發並且必須保持運行。 所以,現在我不得不觸發第二次超時。 但這裏沒有second timeout

我想知道是否有任何替代方法,因爲我不能真正預測在運行時會有多少圖表。

Question 1 : Can we flood our browser with many timeout's?

Question 2 : How to get the id of that particular timeout, so that I can clearTimeout(id) on it?

Question 3 : Since we can't assign/make variables on the fly, how to set/make such a data structure which can hold such a pointer to the particular chart's index/id.. so that we can easily get hold of it and clear it.

Question 4 : Is this the only way we can poll the server(via AJAX) if we have to poll continually?

最後,我承認這是一個非常complex問題我已經張貼在這裏。但我相信我會從論壇中找到一些有用的信息。 我沒有太多的經驗做所有這些東西在JS中,但任何幫助表示讚賞!


更新

對不起,我要發佈我的代碼在這裏。但我使用ExtJS的,讓我的圖表的portlet。我對功能connectToVM代碼是這樣的:

function connectToVM(portalId, host, port, user, passwd, db) { 
     try{ 
     if(Ext.getCmp(portalId)) 
     { 
      var gaugeChartForTitle = Ext.getCmp(portalId); 

      if(typeof portalOriginalTitle === 'undefined') 
       portalOriginalTitle = gaugeChartForTitle.title; 

      var gaugeChartDiv = document.getElementById(portalId); 

      Ext.Ajax.request({ 
         url: "/connectToVM?" + 
          Ext.urlEncode({ 
           host: host, 
           port: port, 
           user: user, 
           passwd: passwd, 
           db: db 
          }), 
         method: 'GET', 
         success: function (response, options) { 

          if(response.responseText !== "") 
          { 
           gaugeChartDiv.style.background = ""; 

           gaugeChartForTitle.setTitle(portalOriginalTitle); 

           console.log("Virtual Machine at "+ host +" : BUSY % : "+response.responseText); 

           virtualMachineStore.loadData(generateVirtualMachineData(response.responseText)); //Setting the data1 value of the store and loading it for display! 

           windowInterval = window.setTimeout(function() { 
            connectToVM(portalId, host, port, user, passwd, db) 
           } 
           , 4000); 
          } 
          else 
          { 
           windowInterval = window.setTimeout(function() { 
            connectToVM(portalId, host, port, user, passwd, db) 
           } 
           , 10000); //Retry every 10 seconds to check if the connection is established! 

           gaugeChartDiv.style.background = "red"; 
           gaugeChartForTitle.setTitle(portalOriginalTitle +" - Connection Failure. Reconnecting!"); 
          } 
         }, 
         failure: function (result, request) { 
        } 
       }); 
     } 
      } 
      catch(err) { 
      } 
     } 

現在,我用這觸發我的功能:

function setWindowIntervalForVM(portalId) { 
     //console.log("isIntervalActivated inside setWindowIntervalForVM() : "+isIntervalActivated); 
     if(!isIntervalActivated) { 
      connectToVM(portalId, host, port, user, pwd, db); 
     } 
    } 

    function checkIfWindowIntervalIsActivated(portal) { 
     if(!isIntervalActivated) { 
      setWindowIntervalForVM(portal.id); 
      isIntervalActivated = true; 
     } else { 
      window.clearInterval(windowInterval); 
      windowInterval = null; 
      isIntervalActivated = false; 
     } 
    } 

所以checkIfWindowIntervalIsActivated()是我的父函數調用,我在這些情況下撥打:

1)每當新創建Gauge Chart ..我觸發該調用,並有boolean isIntervalActivated如果是false其中,觸發SER調查。

2)所以,現在如果我已經在標籤1(因爲用戶選擇它)的圖表,我現在改爲tab 2,它沒有它。於是我簡單地設置isIntervalActivated爲true其停止調查。 This is handled for 1 chart。現在,這裏的問題是,如果我想使這個功能re-usable,說我要放棄的相同type多了一個圖表,但不同的server parameters輪詢,如何利用同樣的windowInterval變量,有我的第一圖表的觸發超時值。 P.S:每一個Ajax請求的值都會改變。所以there'z沒有1 single值:(

3)我停止投票時沒有其他選項卡相同類型的存在..的chart。這很有道理。現在,每當用戶在新的portlet滴/頁面負載,拉力所有用戶配置的門戶我緩存我所有的portlet。在這樣的case,我要觸發所有charts' Ajax調用的..每個輪詢其configured destination。現在,我不知道會有多少個圖表,就像我的函數名稱一樣,我正在輪詢VM。所以如果用戶使用VM1,它將切換到VM2等等。

所以這是絕對不可能的只是創建相同的功能,對於很多這種類似的圖表。 所以只是想檢查,如果我能re-use相同的超時的事情,或採取完全different的辦法處理這一問題:(:(

我希望這是一個有點清楚了,如果不是我能解釋我的情況了。 請讓我更多的問題如果需要的話:)再次 謝謝!

+1

此問題可能會被關閉 - 您需要簡潔並提出一個問題,最好是代碼示例支持,指向您已經研究過的相關信息的鏈接等。請閱讀有關如何提問的常見問題解答這裏。 – Madbreaks 2013-04-30 22:01:16

+0

對不起,我用'code samples'編輯我的問題。 – 2013-04-30 22:05:37

回答

1

如果我理解正確,你正在試圖支持多個圖表同時更新,我會從保持connectToVM()瓶蓋內的圖表數據切換到明確的圖表對象數組並使用一個間隔來更新所有圖表。

像下面這樣(把它當作僞代碼):

var charts = [ 
    // an array of chart objects, see addChart() 
]; 

function addChart() { 
    // when you need to add or remove a chart, update the charts object, like this: 
    charts.push({ 
    update: updateChart, 
    nextUpdateTime: null, // or Date.now() if you don't care about old browsers. 
    chartData: {host: ..., port: ..., user: ..., passwd: ..., db: ..., 
       originalTitle: ..., portalId: ...}, 
    }); 
    restartUpdates(); 
} 

var activeInterval = null; 
function restartUpdates() { 
    if (activeInterval) { 
    clearInterval(activeInterval); 
    } 
    activeInterval = setInterval(updateCharts, 5000); 
} 

// updates all active charts 
function updateCharts() { 
    var now = new Date().getTime(); 
    for (var i = 0; i < charts.length; i++) { 
    var chart = charts[i]; 
    if (chart.nextUpdateTime !== null && chart.nextUpdateTime < now) { 
     chart.nextUpdateTime = null; // chart.update() will re-set this 
     try { 
     chart.update(chart); 
     } catch(e) { 
     // handle the error 
     } 
    } 
    } 

// update a single chart. 
// @param |chart| is an item from the |charts| array. 
function updateChart(chart) { 
    // ...same as your connectToVM() using properties from chart.chartData... 
    Ext.Ajax.request(
    // ... 
     success: function (response, options) { 
     // ...same as before... 
     // ...but instead of re-setting the timeout: 
     // windowInterval = window.setTimeout(function() { 
     //  connectToVM(portalId, host, port, user, passwd, db) 
     //  } 
     // , 4000); 
     // ...update the chart's nextUpdateTime: 
     chart.nextUpdateTime = (new Date().getTime()) + 4000; 
     } 
); 
} 

最初的回答下面

感謝詳細的問題!它感覺你錯過了一些非常明顯的問題#2/3,但很難說沒有看到更多的代碼。你可以發佈一個更完整的,很簡單的例子來證明你正試圖解決的問題嗎?也許功能處理改變僞有源標籤會有所幫助,像這樣:

function selectTab(tabID) { 
    // ...activate tab #tabID in the GUI... 
    if (tabID == 1) { 
    // there's chart #1 on tab #1, need to stop any active timeouts and start a new one 
    connectToVM("chart #1"); 
    } else if (tabID == 2) { 
    // no charts on tab #2.. need to stop any active timeouts 
    } else if (tabID == 3) { 
    // ... 
    } 
} 

有一件事我不明白的是,是否總有一個圖表,需要更新,在任何時間點?

另外,你知道A re-introduction to JavaScript中提到的概念,特別是對象嗎?

至於問題:

  • 1:是的,太多的超時,應避免(千分之一秒將可能使CPU熱和瀏覽器低迷),但我會更擔心服務器,它必須處理來自多個客戶端的請求。
  • 2/3:見上。
  • 4:Comet頁面列出了許多基本的AJAX輪詢(服務器發送的事件,長輪詢,websockets)的替代方案,但我稍後會擔心這一點。
+0

感謝您的回覆Nickolay ..並感謝您提供的鏈接..我知道並實現鏈接中提到的所有這些概念:|是的,關於反向ajax/comet,我們稍後會到達那裏,因爲我已經知道該怎麼做了:)我已經在我的原始問題中發佈了我的代碼和詳細註釋!再次感謝。希望能得到答覆:) – 2013-05-01 20:58:29

+1

@FirstBlood:看到我的答案的更新。 – Nickolay 2013-05-01 21:37:22

+0

太棒了:-)我喜歡你的方法\ m /。我會嘗試一下,並讓你知道它是否可行:)我正在做一個緩存/鍵值類的事情來存儲變量作爲我的超時ID。但是我讀過'String',因爲超時ID不好。涼。 只是想告訴你,我的connectToVM方法現在看起來像這樣: ''''''''''''''''''''' 'pollInterval'&'retryInterval'也是如此。 再次感謝:) – 2013-05-01 23:06:09

1
  1. var x = window.setTimeout(...); window.clearTimeout(x);
  2. 店爲活動選項卡上的數據屬性,屬性在對象上,或者作爲一個全局變量。很多不同 方法。示例代碼可以更容易地回答這個問題。

根據您的意見:

var windowInterval; 
function connectToVM(portal) { 
    if(windowInterval)window.clearTimeout(windowInterval); 
    windowInterval = window.setTimeout(function() { ... }, 4000); 
} 
+0

我完全和你提到的一樣!我正在做。我的變量的範圍也是全局的。但是現在我必須使用它內部具有'setTimeout'的相同函數。所以現在,在這種情況下,我不能使用相同的全局變量,因爲我必須停止通過傳入變量隨時需要第二個新添加的圖表。另外,如果我做'window.clearTimeout(x)';其中x是賦值變量,對於每個新添加的圖表,調用第三個圖表的'clearTimeout(x)',將停止所有3個圖表的超時。:( – 2013-04-30 22:06:30

+0

嗯,不可能有一個變量停止三個不同的超時。當你再次設置全局變量時,它將覆蓋前面的值,而且你不應該僅僅對活動標籤進行Ajax調用,因爲更新用戶不會看到的數據是沒用的嗎? – epascarello 2013-04-30 22:12:51

+0

是的,我只是爲了Ajax調用正如你所提到的那樣,全局變量的值將覆蓋之前的值。我應該如何跟蹤誰觸發了這個函數。因爲,當用戶切換到新選項卡,並且該選項卡沒有該圖表時,我必須停止輪詢服務器。我所有的問題是,只要他沒有在其他選項卡中找到它,就會保留一個軌道和'clearTimeout'。順便說一句,我已經處理了1個圖表的情況..因爲我們可以很容易地保持一個timeOut的軌道..我通過簡單地設置一個'boolean'來觸發該調用! – 2013-04-30 22:19:48