1

这可能是一个新手问题,但是.... 最近,我一直在使用 window.setTimeout 对父函数进行递归调用,从而对服务器进行 ajax 轮询。

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

windowInterval是我的全局变量。

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

现在,不是在这里使用变量,我知道我可以简单地传递functionto clearTimeout,但这也会导致所有其他间隔停止:(

我这样做的原因是服务器超时,只有当有响应时。我的情况是,我有一个图表,它会更新每个超时间隔。AFAIK,当我们设置间隔时,会为变量设置一个特定的值(如果设置为变量)。因此,当我打印我的变量时(每次调用超时函数时),我都会得到一些唯一的 int 值。

我有很多选项卡,许多选项卡可以有相同的图表..这只是利用了之前触发的相同间隔。现在我只有一张图表。但我有很多图表可以显示哪些是相同类型的。说仪表图表。

每当当前选定的选项卡中没有图表时,我还必须清除超时 - 我正在这样做。所以我打算只做一个函数,它只是通过将所需的参数传递给这个函数来调用服务器。

但是为了进行投票,我使用了上面提到的 window.setTimeout 东西。这适用于 1 个图表。现在,我尝试再添加 1 个图表,使用不同的参数集来轮询服务器,我需要使用一些不同的 setTimeout 函数,它的 id 与之前触发的超时不同。

我还必须考虑,如果第一个图表已经存在,则超时已经触发并且必须保持运行。所以,现在我必须触发第二次超时。但是这里没有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,触发服务器轮询。

2)所以现在如果我已经在选项卡 1 中有图表(因为用户选择了它),我现在更改为tab 2没有它。所以我只是设置isIntervalActivated为 true 来停止投票。This is handled for 1 chart. 现在这里的问题是,如果我想创建这个函数re-usable,假设我想再删除一张相同type但与server parameters轮询不同的图表,如何使用windowInterval具有我的第一个图表的触发超时值的相同变量。PS:它发出的每个 ajax 请求的值都会发生变化。所以没有1 single价值:(

3)只要在其他选项卡中没有chart相同类型的存在,我就会停止投票。这很有意义。现在,每当用户在页面加载时放入一个新的 portlet / 时,我都会缓存我的所有 portlet,拉取所有用户配置的 portlet。在这样的情况下case,我必须触发所有的charts'ajax 调用configured destination。现在,我不知道会有多少图表,就像我的函数名称一样,我正在轮询 VM。所以如果用户消费了VM1,它就会切换到VM2,以此类推。

因此,绝对不可能为许多类似的图表创建相同的功能。所以只是想检查一下我是否可以re-use做同样的事情,或者完全different解决这个问题:( :(

我希望现在有点清楚,如果没有,我可以更多地解释我的情况。如果需要,请问我更多问题:) 再次感谢!

4

2 回答 2

1
  1. 是的
  2. var x = window.setTimeout(...); window.clearTimeout(x);
  3. 将其存储为活动选项卡上的数据属性、对象上的属性或全局变量。许多不同的方式。示例代码会更容易回答这个问题。

根据您的评论:

var windowInterval;
function connectToVM(portal) {
    if(windowInterval)window.clearTimeout(windowInterval);
    windowInterval = window.setTimeout(function() { ... }, 4000);
}
于 2013-04-30T22:00:57.630 回答
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;
      }
  );
}

下面的初步答案

感谢您的详细问题!感觉你错过了一些非常明显的 wrt 问题 #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)的替代方案,但我稍后会担心这个。
于 2013-05-01T02:36:39.473 回答