20.12.2017, 15:48
|
Кандидат Javascript-наук
|
|
Регистрация: 18.09.2014
Сообщений: 128
|
|
Как заставить javascript работать нормально?
document.body.innerHTML = "";
for(var i=0;i<3;i++){
document.body.innerHTML+="Hi! ";
alert();
}
Как я хочу, чтобы работала программа:
1. Очистила элемент body.
2. Написала "Hi! "
3. Выдала alert.
4. После закрытия alert ещё раз написала "Hi !".
5. Выдала alert.
4. После закрытия alert ещё раз написала "Hi !".
5. Выдала alert.
Как она работает вместо этого, вы видите.
Как сделать так, чтобы программа работала так как я хочу (и как она работала бы в PHP, Java, C и т.д.)?
Очень удивил stackoverflow: https://stackoverflow.com/questions/...78675_47905481
Я думал, что мой вопрос настолько базовый, что мне немедленно дадут ссылку на матчасть. Вместо этого они пишут, что мой вопрос - дубликат вопроса "Давай покрасим холодильник в чёрный цвет" и предлагают кучу решений, которые НЕ РАБОТАЮТ.
|
|
20.12.2017, 16:28
|
|
Тлен
|
|
Регистрация: 02.01.2010
Сообщений: 6,590
|
|
В firefox проблемы нет. Closed: Worksforme.
Пишите письма в багтреккер хрома.)
Вообще причина, очевидно, в том, что вызов alert почему-то не считается хромом достаточной причиной для перерисовки. В обычном случае действительно не имеет смыла перерисовывать страницу после каждого шага цикла, т.к. цикл неделимая операция, но по логике вещей alert или какой-нить yield должен таки тригерить это действие.
Принудительный requestAnimationFrame, конечно порешает проблему, но, имхо, данная ситуация если не баг то хреновый код. (Полагаю причина в принципиальном презрении к самому alert )
__________________
29375, 35
Последний раз редактировалось Aetae, 20.12.2017 в 16:41.
|
|
20.12.2017, 16:46
|
Кандидат Javascript-наук
|
|
Регистрация: 18.09.2014
Сообщений: 128
|
|
|
|
20.12.2017, 16:54
|
|
Тлен
|
|
Регистрация: 02.01.2010
Сообщений: 6,590
|
|
Сообщение от jaroslav.tavgen
|
У меня в Firefox работает абсолютно так же.
|
Абсолютно также это как?)
http://ajitae.tk/test/2.html
FF57.0.2 64bit win7, win8 - всё как надо.
__________________
29375, 35
|
|
20.12.2017, 17:04
|
Кандидат Javascript-наук
|
|
Регистрация: 18.09.2014
Сообщений: 128
|
|
Да, прошу прощения, это я перепутал. Всё правильно. Спасибо большое, за ответ! Я посмотрю, как моя программа (не эта, а настоящая) работает в Firefox, и тогда возможно поподробнее напишу
|
|
20.12.2017, 17:32
|
Кандидат Javascript-наук
|
|
Регистрация: 18.09.2014
Сообщений: 128
|
|
Всё ясно, в моей программе была ошибка совсем другого плана.
Aetae, спасибо большое!
|
|
20.12.2017, 17:53
|
Кандидат Javascript-наук
|
|
Регистрация: 18.09.2014
Сообщений: 128
|
|
И все-таки вопрос у меня есть.
document.body.innerHTML = "";
for (var i=0;i<1000000;i++){
document.body.innerHTML += "a";
}
Пока цикл не отработает миллион раз, на экран ничего не будет выведено.
А как сделать так, чтобы он добавлял по одной буковке за раз?
|
|
20.12.2017, 18:51
|
|
Профессор
|
|
Регистрация: 19.01.2012
Сообщений: 505
|
|
<html><body></body></html>
<script>
document.body.innerHTML = "";
var end=500;
(function tick(i) {
document.body.innerHTML += "a";
if(i<end) setTimeout(tick.bind(null, i+1), 1);
})(0);
</script>
Последний раз редактировалось Белый шум, 20.12.2017 в 18:54.
|
|
20.12.2017, 19:00
|
|
Профессор
|
|
Регистрация: 07.03.2011
Сообщений: 1,138
|
|
Сообщение от jaroslav.tavgen
|
А как сделать так, чтобы он добавлял по одной буковке за раз?
|
В цикле практически ни как.
JS строго однопоточен. т.е. использовать несколько потоков в одном контексте исполнения невозможно.
в JS невозможно ограничить область видимости одного потока от области видимости другого потока (глобальный объект, цепочка прототипов) доступны всем и всегда. Изменения данных в одном потоке сделают непредсказуемым результат работы в другом потоке.
самый простой способ обойти блокировку других задач (рендеринга) пока работает долгий код это разбить задачу вызовами асинхронной функции setTimeout (задача,0) т.е. запустить/продолжить задачу после того как браузер сделает все ожидающие операции.
небольшой пример
<body><script>
function repeat (fun,size){
+function asd (){
fun();
if (size % 110 == 0) document.body.innerHTML += "<br>";
if ( --size > 0) setTimeout (asd,0);
}();
}
function idiotizm (){
document.body.innerHTML += "a";
}
repeat (idiotizm , 6000);
</script>
Последний раз редактировалось MallSerg, 20.12.2017 в 19:05.
|
|
20.12.2017, 22:03
|
|
Тлен
|
|
Регистрация: 02.01.2010
Сообщений: 6,590
|
|
Добавлю для ясности: однопоточность означает, что пока поток занят циклом, он физически не может ничего рисовать. Цикл - единичный неделимый блок. Чтобы гарантировано, сразу по возможности(fps), результат появлялся на экране - придумали requestAnimationFrame, но за отсутствием(старый ослик) и setTimeout пойдёт.
__________________
29375, 35
Последний раз редактировалось Aetae, 20.12.2017 в 22:06.
|
|
|
|