Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 17.12.2012, 21:06
Аватар для cib
cib cib вне форума
Интересующийся
Отправить личное сообщение для cib Посмотреть профиль Найти все сообщения от cib
 
Регистрация: 11.12.2012
Сообщений: 16

Cтранное поведение цикла for
Цикл при явном видимом ограничении на 2 прохода заходит в себя третий раз. Не имею ни одной здравой мысли почему так.



Дополню:

функция теперь выглядит так:

function func1() {
  if(...){
     //some code #1
     var _ic = _Items.length;
     for( var i = 0; i < _ic; i++ ) {
       $('#tw2logn').append( _Items[ i ].ID + ', ' );
     }
     //some code #2
  } else {
     //some code #3
  }
  setTimeout( function() { func1(); }, timeout1 );
}


Во время работы указанного цикла происходит классический out of range и вместо креша исполнение вылетает из if-else и таймаут спокойно отрабатывает, но при этом теряется кусок "some code #2". А в логе имеем "Item1, Item2,".

Последний раз редактировалось cib, 17.12.2012 в 21:28.
Ответить с цитированием
  #2 (permalink)  
Старый 17.12.2012, 21:16
Аватар для Shaci
:-/
Отправить личное сообщение для Shaci Посмотреть профиль Найти все сообщения от Shaci
 
Регистрация: 28.09.2009
Сообщений: 1,126

проверьте , засуньте в тело цикла console.log('step')
должен 2 раза отпечатать слово
Ответить с цитированием
  #3 (permalink)  
Старый 17.12.2012, 21:20
Аватар для cib
cib cib вне форума
Интересующийся
Отправить личное сообщение для cib Посмотреть профиль Найти все сообщения от cib
 
Регистрация: 11.12.2012
Сообщений: 16

в теле цикла, как можно заметить, уже есть вывод хоть и не в консоль, но все равно лог, и выводятся единственные два элемента массива, при обращении по индексу 2 происходит крэш функции и мы вылетаем из нее.
Попробовал создать буферную переменную, но не помогло:
var _ic = _Items.length;
	for( var i = 0; i < _ic; i++ ) {
		$('#tw2logn').append( _Items[ i ].ID + ', ' );
	}


Запустил на других данных так, чтобы был всего один элемент массива, но цикл упорно идет дальше, не глядя на строгое условие
i < _ic
Ответить с цитированием
  #4 (permalink)  
Старый 18.12.2012, 12:17
жажду знаний
Отправить личное сообщение для bushstas Посмотреть профиль Найти все сообщения от bushstas
 
Регистрация: 17.07.2009
Сообщений: 202

так у тебя ведь функция func1 в конце вызывает саму себя и получается замкнутый круг, отсюда out of range.
Нужно ведь по логике какое то условие чтобы она перестала вызывать саму себя в какой то момент, разве нет?

И вообще зачем она вызывает саму себя в конце?

Ведь получается как бы два цикла один FOR который безошибочно работает другой цикл это функция сама себя вызывающая

или если это какой то постоянный процесс так нужно чтобы интервал между вызывами был нормальный,
может в длительности интервала проблема?

возможно строка setTimeout( function() { func1(); }, timeout1 ); должна находится внутри последнего else {}

Последний раз редактировалось bushstas, 18.12.2012 в 12:22.
Ответить с цитированием
  #5 (permalink)  
Старый 18.12.2012, 12:45
Аспирант
Отправить личное сообщение для Sanda Посмотреть профиль Найти все сообщения от Sanda
 
Регистрация: 12.10.2012
Сообщений: 90

_Items случаем не какой-нибудь live collection? Очень похожее поведение - в консоли свойства могут и не обновляться (: Попробуйте в момент лишнего захода в цикл кликнуть на _Items.length правой кнопкой и обновить значение.
Ответить с цитированием
  #6 (permalink)  
Старый 18.12.2012, 16:11
Аватар для cib
cib cib вне форума
Интересующийся
Отправить личное сообщение для cib Посмотреть профиль Найти все сообщения от cib
 
Регистрация: 11.12.2012
Сообщений: 16

Отвечаю по порядку:
1. таймаут нужен для того, чтобы периодически непрерывно вызывать func1, причем время таймаута не фиксированное, а может меняться.
2. Единственное условие завершение периодичного вызова самой себя - уход со страницы (перезагрузка). Поэтому setTimeout должен вызываться в любом случае, поэтому он вынесен из if-else. Да и вообще в данном случае таймаут никак не может повлиять на работу, потому что работает это так:
1. func1 выполняет свой код
2. func1 планирует сама себя на выполнение через N ms
3. ничего не происходит N ms
4. func1 выполняет свой код
5. func1 планирует сама себя на выполнение через M ms
6. ничего не происходит M ms
и т.д. пока юзер не уйдет с сайта. Учитывая, что условие в for проверяется при каждой итерации цикла (и писать 'i < _Item.length' вообще говоря муветон с точки зрения производительности), а _Items является локальной переменной func1 и нигде за ее пределами в других потоках не меняется, то таймаут тут ну вообще ни при чем.
Но всё это (пп.1-2) не касается проблемы как таковой, потому что: а) похожий цикл for чуть ранее в some code #1 работает нормально, и б) см.п.3 и P.S.
3. описаное безобразие происходит при первом входе в функцию, т.е. цикл for сходит с ума в первый же раз, и только потом вызывается таймаут, т.о. он никак не влияет на выполнение func1 в первую итерацию.
4. Sanda, _Items - массив "объектов", содержащих 4 текстовых поля, в т.ч. ID ( например, { 'ID1', 'Field1', 'Field2', 'Field3' } ), которые добавляются в массив банальным push(). Я пробовал вместо _Item.lеngth передавать туда уже готовое значение и вообще писать руками цифру. Толку ноль.

Причинно-следственная связь простая:
причина - условие i < _ic не срабатывает при i==2 и _ic==2
следствие - statement крэшится и мы теряем some code#2

P.S. попробовал вместо '_ic' в условиях написать тупо '2'
for( var i = 0; i < 2; i++ ( {
   //бла-бла
}

Не помогло. Цикл по прежнему прется на третью итерацию и крешится.
Ответить с цитированием
  #7 (permalink)  
Старый 18.12.2012, 16:33
Аспирант
Отправить личное сообщение для Sanda Посмотреть профиль Найти все сообщения от Sanda
 
Регистрация: 12.10.2012
Сообщений: 90

Утверждение 1. Чудес не бывает.
Утверждение 2. Если Вы видите чудо, см. утв. 1.

Могу предложить сделать следующие вещи:
1. Создать коллекцию из N > 2 элементов, а в цикле поставить i < 1. Посчитать количество срабатываний.
2. Сделать в цикле console.log(i), console.log(_ic), console.log(i < _ic), console.log(i - _ic), try{console.log(_Items[i])}catch(e){console.log(e)}. Как при обычном выполнении, так и при условии 1.
3. Проанализировать результаты.
4. Выложить их сюда.
5. ???
6. PROFIT!!!

Пп. 3 и 4 выполнять строго в вышеуказанной последовательности. Вывод в консоль можно делать дважды - до выполнения действия и после него же.
Ответить с цитированием
  #8 (permalink)  
Старый 18.12.2012, 17:39
Аватар для cib
cib cib вне форума
Интересующийся
Отправить личное сообщение для cib Посмотреть профиль Найти все сообщения от cib
 
Регистрация: 11.12.2012
Сообщений: 16

Sanda,
Далее копипаста из исходников.

Расшифровка:
"Работает как положено" - цикл выполняется столько раз, сколько задано условием, т.о. до отлова исключения дело не доходит.
"Out of range" - цикл идет на итерацию с нарушением условия.

Пишу:
var _Items = [ 1, 2, 3 ];
var _ic = _Items.length;
for( var cnt = 0; cnt < _ic; cnt++ ) {
	console.log( cnt );
	console.log( _ic );
	console.log( cnt < _ic);
	console.log( cnt - _ic);
	try{console.log(_Items[cnt])}catch(e){console.log(e)}
}

Работает как положено.

Пишу:
var _Items = [ 1, 2, 3 ];
var _ic = 1;
for( var cnt = 0; cnt < _ic; cnt++ ) {
	console.log( cnt );
	console.log( _ic );
	console.log( cnt < _ic);
	console.log( cnt - _ic);
	try{console.log(_Items[cnt])}catch(e){console.log(e)}
}

Работает как положено.

Пишу:
var _ic = _Items.length;
for( var cnt = 0; cnt < _ic; cnt++ ) {
	$('#tw2logn').append( _Items[ cnt ].ID + ', ' );
}

Out of range.

Пишу:
var _ic = 1;
for( var cnt = 0; cnt < _ic; cnt++ ) {
	$('#tw2logn').append( _Items[ cnt ].ID + ', ' );
}

Out of range.

Начинаю грешить на jQuery.

Пишу:
var _ic = _Items.length;
for( var cnt = 0; cnt < _ic; cnt++ ) {
	try{console.log(_Items[cnt].ID)}catch(e){console.log(e)}
}

Out of range. В консоли только ID из массива.

Пишу:
var _ic = 1;
for( var cnt = 0; cnt < _ic; cnt++ ) {
	try{console.log(_Items[cnt].ID)}catch(e){console.log(e)}
}

Out of range. В консоли только ID из массива.

P.S. не знаю насколько это важно, но в любой ситуации при out of range мой statement не просто крэшится, а передает следующий шаг по отладке в jQuery, а оттуда уже эвакуация из statement'а.
Ответить с цитированием
  #9 (permalink)  
Старый 18.12.2012, 17:43
Аватар для cib
cib cib вне форума
Интересующийся
Отправить личное сообщение для cib Посмотреть профиль Найти все сообщения от cib
 
Регистрация: 11.12.2012
Сообщений: 16

На ум приходит аналогия работы калькулятора:
exe: 1+1+1+1
out: 4
exe: 2+2
out: 5
Ответить с цитированием
  #10 (permalink)  
Старый 18.12.2012, 17:50
Аватар для cib
cib cib вне форума
Интересующийся
Отправить личное сообщение для cib Посмотреть профиль Найти все сообщения от cib
 
Регистрация: 11.12.2012
Сообщений: 16

Вставляю пустую строку между for(){} и //somecode#2 - и цикл начинает работать как положено.
Убираю пустую строку между for(){} и //somecode#2 - и цикл идет на итерации out of range:

Работает:
for( var cnt = 0; cnt < _Items.length; cnt++ ) {
	$('#tw2logn').append( _Items[ cnt ].ID + ', ' );
}

$('#tw2logn').append( '<br>' );

Не работает:
for( var cnt = 0; cnt < _Items.length; cnt++ ) {
	$('#tw2logn').append( _Items[ cnt ].ID + ', ' );
}
$('#tw2logn').append( '<br>' );


Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Логика действий на примере цикла for ufaset Общие вопросы Javascript 1 27.11.2011 22:04
Как взятые данные с цикла присоединить к одной переменной ? saturn Элементы интерфейса 2 25.11.2011 13:01
Cтранное поведение viktod Общие вопросы Javascript 23 10.04.2010 00:37
Странное поведение replace cooli0 Общие вопросы Javascript 4 25.01.2010 17:16
как отобразить в окне значения счетчика во время выполнения цикла FOR Алекс97 Общие вопросы Javascript 5 06.09.2008 10:36