Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Замыкания... почему alert "глючит" ? (https://javascript.ru/forum/misc/60475-zamykaniya-pochemu-alert-glyuchit.html)

Keramet 02.01.2016 17:30

Замыкания... почему alert "глючит" ?
 
Есть 2 фрагмента, каждый из которых через 3 секунды выводит i (от 1 до 10). Но вот почему-то во втором (с alert) порядок нарушен. console.log выводит всё правильно (от 1 до 10.) Почему?
1.
for (var i = 1; i <= 10; i++) {
		(function(e) {
			setTimeout(function() {
				console.log(e);
			}, 3000);
		})(i);
	}


2.
for (var i = 1; i <= 10; i++) {
		(function(e) {
			setTimeout(function() {
				alert(e);
			}, 3000);
		})(i);
	}

рони 02.01.2016 17:45

Keramet,
потому что у вас долгая реакция на кнопку ок, а у Google Chrome мания всё оптимизировать, так как он считает нужным.

Keramet 02.01.2016 17:51

рони, т.е. на других броузерах alert выдаст всё по порядку?

рони 02.01.2016 17:53

Keramet,
да

рони 02.01.2016 18:02

Keramet,
уберите for и всё будет по порядку везде и без замыканий :)

Keramet 02.01.2016 18:35

Цитата:

Сообщение от рони (Сообщение 402249)
Keramet,
уберите for и всё будет по порядку везде и без замыканий :)

т.е. другой цикл использовать?

рони 02.01.2016 18:42

Keramet,
одна функция с условием запуска без циклов

рони 02.01.2016 18:53

Keramet,
var i = 0;
		(function fn() {
		  i  &&  alert(i);
          i++;
		  i < 11 &&	setTimeout(fn, 3000);
		})();

Keramet 02.01.2016 19:21

Цитата:

Сообщение от рони (Сообщение 402253)
Keramet,
var i = 0;
		(function fn() {
		  i  &&  alert(i);
          i++;
		  i < 11 &&	setTimeout(fn, 3000);
		})();

Интересное решение. А зачем в строке 3 i && alert(i);
. Почему нельзя просто alert(i); ? (чтобы ноль не выводить?)

рони 02.01.2016 19:41

Keramet,
чтобы первый алерт был не сразу а через 3 секунды

callbackhell 02.01.2016 20:35

Цитата:

Сообщение от рони
а у Google Chrome мания всё оптимизировать, так как он считает нужным.

А, где-нибудь в стандарте прописана гарантия, что колбеки должны вызываться в том порядке в котором выброшены?

Keramet 02.01.2016 20:37

Цитата:

Сообщение от callbackhell (Сообщение 402269)
А, где-нибудь в стандарте прописана гарантия, что колбеки должны вызываться в том порядке в котором выброшены?

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

callbackhell 02.01.2016 20:54

Цитата:

Сообщение от Keramet
мне кажется, это было бы логично (я имею ввиду, вызывать в "правильном" порядке

Да нет. Асинхронное программирование оно такое. Нет там гарантии порядка, при необходимости надо синхронизировать, и это логично. Я правда, не знаю, как в JS обстоит, поэтому и спросил.

Keramet 02.01.2016 20:56

Асинхронное - я так понимаю, основанное на событиях, где нет четкого распорядка выполнения команд. но в нашем примере (10раз подряд вывести что-то, ключевое как раз и есть - подряд, по порядку). Было б логично и получить результат в нужном порядке )

callbackhell 02.01.2016 20:58

Keramet,

таймаут -- это тоже событие. Ваши коллбеки выстреливают по этому событию. Просто в js дохрена подковерной возни и противоречивый синтаксис.

callbackhell 02.01.2016 21:05

Keramet,
Чтобы проще было это понять, представьте себе, что у нас есть объект таймаут
Timeout.setTimeout(callback)
//В объект таймаут записывется некий слот, скажем, onTimeout = callback
// а где то на уровне реализации по событию таймаута движок вызывает этот коллбек
onNextTick = function(){Timeout.onTimeout()}

Вот так все реально и происходит, просто многое скрыто от ваших глаз, и это приводит к непоняткам.

Keramet 02.01.2016 21:08

в примере с выводом 10, можно считать вывод числа 2 функцией обратного вызова (ФОВ) к выводу числа 1; вывод 3 - ФОВ от вывода 2 и т.д.?

callbackhell 02.01.2016 21:11

Цитата:

Сообщение от Keramet
в примере с выводом 10, можно считать вывод числа 2 функцией обратного вызова (ФОВ) к выводу числа 1; вывод 3 - ФОВ от вывода 2 и т.д.?

Я вас не понял. Читайте внимательно мой предыдущий пост. То что Вы сказали, к реальности вообще отношения не имеет. У вас на каждой итерации коллбеки из setTimeout кидаются в очередь на событие таймаута, когда событие наступает, они вызываются на уровне реализации, движком.

callbackhell 02.01.2016 21:13

Keramet,
Вы как бы говорите движку: Когда событие наступит вызови вот эти коллбеки.

Keramet 02.01.2016 21:16

Возможно я не совсем корректно выразился:
что такое функция обратного вызова - это функция, которой передаётся управление только после того, как полностью закончит свою работу вызвавшая её функция. правильно?
Я поэтому и спросил, можно ли считать (хотя бы образно), что вывод числа 2 (будем образно считать вывод числа 2 функцией обратного вызова) должен произойти только после того, как произойдет вывод числа 1 (а вывод числа 1 - это функция, по окончанию работы которой вызывается наша ФОВ).
Вух - ни и заплёл я - надеюсь, смысл понятен ;)

callbackhell 02.01.2016 21:17

Цитата:

Сообщение от Keramet
что такое функция обратного вызова - это функция, которой передаётся управление только после того, как полностью закончит свою работу вызвавшая её функция. правильно?

Это только в синхронном варианте. В данном случае, вы делегируете вызов этих функций движку. Все что делает ф-ция setTimeout -- бросает коллбек в некий массив, из которого он позже будет вызван. Термин не слишком удачен, да.

рони 02.01.2016 21:18

Keramet,
для хрома приоритет время -- время таймера подошло он пытается его сначала выполнить, затем смотрит очередь , если нельзя выполнить ставит в очередь, в других браузерах сразу кидают в очередь, потом пытаются выполнить.

Keramet 02.01.2016 21:27

Цитата:

Сообщение от callbackhell (Сообщение 402289)
Это только в синхронном варианте. В данном случае, вы делегируете вызов этих функций движку. Все что делает ф-ция setTimeout -- бросает коллбек в некий массив, из которого он позже будет вызван. Термин не слишком удачен, да.

т.е. наш вывод чисел от 1 до 10 набросал команд в этот некий массив, так? и вывод на экран почему-то происходит не в том порядке, в котором они туда попали. в этом и проблема. правильно я понял?

callbackhell 02.01.2016 21:29

Цитата:

Сообщение от Keramet
вывод на экран почему-то происходит не в том порядке, в котором они туда попали. в этом и проблема. правильно я понял?

Скорей всего они туда попадают не в том порядке, в котором кидаются.

Keramet 02.01.2016 21:33

Цитата:

Сообщение от callbackhell (Сообщение 402294)
Скорей всего они туда попадают не в том порядке, в котором кидаются.

О, это уже интереснее: они туда попадают не в том порядке, или они оттуда извлекаюстя не в том порядке? или и то, и то :)

П.С. мне нравится ваше Скорее всего ;)

callbackhell 02.01.2016 21:39

Keramet,
Я не писал реализацию V8, извините. Но Вам это и не нужно знать. Просто имейте в виду, что порядок не гарантируется, этого достаточно.

Keramet 02.01.2016 21:57

callbackhell,
Это я уже понял, что порядок не гарантируется :) в этом то и состоял вопрос - почему!! или я что-то накодил..., или глюк какой-то. Вариант Рони работает, но он мне как-то эстетически не нравиться - это моё субъективное мнение ;)

рони 02.01.2016 22:06

Keramet,
так не используйте алерт и ваш вариант тоже сработает как надо если уложатся в 3 секунды все заботы браузера.

callbackhell 02.01.2016 22:08

Цитата:

Сообщение от рони
как надо

Что значит "как надо"? В стандарте есть это? Или Вы имеете в виду, как ожидал ТС?

рони 02.01.2016 22:15

Цитата:

Сообщение от callbackhell
как ожидал ТС

да


Часовой пояс GMT +3, время: 11:15.