Использование window.setTimeout() и window.setInterval() в этой ситуации

54
4

Это может быть вопрос newb, но... Недавно я использовал window.setTimeout, который делает рекурсивный вызов родительской функции, что делает опрос ajax для сервера.

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

windowInterval - это мой глобальный var здесь.

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

Теперь вместо того, чтобы использовать здесь переменные, я знаю, что могу просто передать function clearTimeout, но это также приводит к остановке всех остальных интервалов :(

Причина, по которой я делаю это, - это сервер, который выполняет тайм-аут, только когда есть ответ. Мой сценарий: у меня есть диаграмма, которая обновляет каждый интервал времени ожидания. AFAIK, когда мы устанавливаем интервал, существует определенное значение, заданное переменной (если установлено значение переменной). Поэтому, когда я печатаю свою переменную (каждый раз, когда вызывается функция тайм-аута), я получаю некоторые значения int, которые являются уникальными.

У меня много вкладок, и многие вкладки могут иметь один и тот же график.., который просто использует тот же интервал, который запускается ранее. Теперь у меня всего 1 график. Но у меня много диаграмм, показывающих, что они одного типа. Скажите калибровочную диаграмму.

Мне также нужно очистить таймаут, если на текущей выбранной вкладке нет графика, который я делаю. Поэтому я планирую сделать только одну функцию, которая просто делает вызов на сервер, передавая необходимые параметры этой функции.

Но для того, чтобы опросить, я использую window.setTimeout, о котором я упоминал выше. Это работает для 1 диаграммы. Теперь я пытаюсь добавить еще 1 диаграмму с различным набором параметров для опроса сервера, мне нужно будет использовать некоторую другую функцию setTimeout, которая имеет идентификатор, отличный от предыдущего таймаута.

Я также должен учитывать, что если 1-й график уже присутствует, тайм-аут уже запущен и должен продолжать работать. Итак, теперь мне нужно запустить второй тайм-аут. Но 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 я 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 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, чтобы получить портлеты диаграмм. Мой код для функции 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 этот вызов и boolean isIntervalActivated который, если он false, запускает опрос сервера.

2) Итак, теперь, если у меня есть диаграмма уже на вкладке 1 (так как пользователь ее выбрал), теперь я перехожу на tab 2 которой ее нет. Поэтому я просто устанавливаю isIntervalActivated в true, который останавливает опрос. This is handled for 1 chart. Теперь вопрос заключается в том, что если я хочу, чтобы эта функция была re-usable, скажем, я хочу отбросить еще одну диаграмму того же type но с различными server parameters для опроса, как использовать ту же переменную windowInterval которая имеет мою windowInterval диаграмму значение тайм-аута. PS: Значение изменяется для каждого запроса ajax, который он делает. Так что нет 1 single значения :(

3) Я останавливаю опрос всякий раз, когда нет chart того же типа... на другой вкладке. что имеет смысл. Теперь я кэширую все свои портлеты всякий раз, когда пользователь падает в новый портлет/на загрузку страницы, вытягивая все портлеты, настроенные пользователем. В таком case я должен запускать все аякс-вызовы charts'.. каждый опрос до его configured destination. Теперь, я не знаю, сколько графиков будет, как и в моем имени функции, я опросу VM. Поэтому, если пользователь потребляет VM1, он переключается на VM2 и так далее.

Поэтому абсолютно невозможно создать такую же функцию для многих подобных подобных диаграмм. Так что просто хотел проверить, могу ли я re-use одно и то же время, или принять совершенно different подход к этой проблеме :( :(

Надеюсь, теперь это станет немного ясным, если не могу объяснить мою ситуацию больше. Пожалуйста, задайте мне больше вопросов, если потребуется :) Еще раз спасибо!

спросил(а) 2013-05-01T00:56:00+04:00 7 лет, 2 месяца назад
1
Решение
55

Если я правильно понял и вы пытаетесь одновременно поддерживать несколько диаграмм, я бы переключился с хранения данных диаграммы внутри закрытия 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 nextUpdateTime:
chart.nextUpdateTime = (new Date().getTime()) + 4000;
}
);
}

первоначальный ответ ниже

Спасибо за подробный вопрос! Кажется, что вам не хватает чего-то очень очевидного вопроса № 2/3, но трудно сказать, что конкретно, не видя больше вашего кода. Можете ли вы опубликовать более полный, да простой пример, демонстрирующий проблему, которую вы пытаетесь решить? Возможно, обработка функций, изменяющих активную вкладку в псевдокоде, поможет:

function selectTab(tabID) {
// ...activate tab #tabID in the GUI...
if (tabID == 1) {
// there 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) {
// ...
}
}

Одна вещь, которую я не понимаю, есть ли всегда одна диаграмма, которая нуждается в обновлении, в любой момент времени?

Кроме того, знаете ли вы понятия, упомянутые в разделе "Повторное введение в JavaScript", в частности объекты?

Что касается вопросов:

    1: да, слишком много тайм-аутов следует избегать (тысячи секунд, вероятно, сделают процессор горячим, а браузер вялым), хотя меня больше беспокоит сервер, который должен обрабатывать запросы от нескольких клиентов. 2/3: см. Выше. 4: На странице Comet перечислены многие альтернативы базовому опросу AJAX (события, отправленные сервером, длинные опросы, веб-сайты), но об этом я буду беспокоиться позже.

ответил(а) 2013-05-01T05:36:00+04:00 7 лет, 2 месяца назад
54

да var x = window.setTimeout(...); window.clearTimeout(x); Храните его как атрибут данных на активной вкладке, свойство на вашем объекте или глобальную переменную. Много разных способов. Пример кода упростит ответ.

Основываясь на ваших комментариях:

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

ответил(а) 2013-05-01T01:00:00+04:00 7 лет, 2 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема