Комментарии 86
а почему бы не разнести UI и исполнение js по разным потокам?
+12
Потому что в большинстве случае вы скорее хотите синхронизации: короткое, почти незаметное для пользователя блокирование UI на время каких-нибудь манипуляций с интерфейсом, вроде обновления элементов через DOM.
Ну и в целом, писать в синхронном режиме проще. Для асинхронного выполнения JS будут веб-воркеры, но они не всемогущи :)
Ну и в целом, писать в синхронном режиме проще. Для асинхронного выполнения JS будут веб-воркеры, но они не всемогущи :)
-1
я говорю с позиции разработчика браузеров — отрисовка UI в своём потоке, исполнение js — в своём.
+8
Это потребует не только введения дополнительной синхронизации (то есть усложнения браузера), но и пересмотра принципов разработки приложений.
0
JS изменяет DOM, Рендерер берёт данные из DOM. Зачем переделывать архитектуру приложений?
Единственное, чего это потребует, это поднять задницу с шезлонга на Мальдивах и написать нормальный браузер. Это невозможно.
Единственное, чего это потребует, это поднять задницу с шезлонга на Мальдивах и написать нормальный браузер. Это невозможно.
+1
Расскажите, пожалуйста,
1) как вы будете сихнронизировать между собой потоки js и ui и реагировать на все изменения в одном или другом и, в частности в dom?
2) в каких нормальных браузерах поток UI полностью отделен от потока JS и вычислительные задержки в JS не приводят к замораживанию интерфейса?
p.s. На всякий случай: веб-воркеры как предлагают отделение кода на js в отдельный поток, но этот поток не умеет взаимодействовать с UI (DOM).
1) как вы будете сихнронизировать между собой потоки js и ui и реагировать на все изменения в одном или другом и, в частности в dom?
2) в каких нормальных браузерах поток UI полностью отделен от потока JS и вычислительные задержки в JS не приводят к замораживанию интерфейса?
p.s. На всякий случай: веб-воркеры как предлагают отделение кода на js в отдельный поток, но этот поток не умеет взаимодействовать с UI (DOM).
0
1) Колбеки? Зачем рендереру знать о том, что происходит в JS?
2) В ФФ вроде бы собираются вводить. Да и вообще, многопоточность — тренд. В нормальных браузерах, в отличии от IE, почему то нет этих 9% зависаний.
ЗЫ: Анекдот.
-Папа, а что такое мультизадачность Windows?
-Погоди, сынок, сейчас дискетку доформатирую и покажу.
2) В ФФ вроде бы собираются вводить. Да и вообще, многопоточность — тренд. В нормальных браузерах, в отличии от IE, почему то нет этих 9% зависаний.
ЗЫ: Анекдот.
-Папа, а что такое мультизадачность Windows?
-Погоди, сынок, сейчас дискетку доформатирую и покажу.
0
1. А это не проблема рендерера. Это проблема того, кто занимается синхронизацией изменений в DOM, рендеринга, операций в JS и реакцией на действия пользователя с UI.
2. Как это нет? Вы пробовали код в Firefox, Chrome или Safari?
2. Как это нет? Вы пробовали код в Firefox, Chrome или Safari?
0
Сейчас тренд это асинхронность а не многопоточность. Многопоточность тренд предыдущего десятилетия.
0
И что?
+1
А что вы хотите услышать в ответ на свой вопрос?
0
Может он имел ввиду, что пора бы уже переписать 90% кода, оставшихся с IE5? :)
Может, сквозные баги исчезнут. Правда, появятся новые, но ничего, хотя бы какое-то веселье вирусописателям будет.
Может, сквозные баги исчезнут. Правда, появятся новые, но ничего, хотя бы какое-то веселье вирусописателям будет.
0
Давайте конкретнее про 90% кода, оставшихся с IE5, и сквозные баги, ага?
+1
Если смайлик для Вас уже просто знак препинания, извините. Это была шутка. Однако в каждой шутке есть доля правды.
Про баги IE писать не буду, погуглите. В конце концов, даже Bing гуглит. :)
Про баги IE писать не буду, погуглите. В конце концов, даже Bing гуглит. :)
0
Смайлик и есть что-то вроде знака препинания ;)
Тем не менее, 90% таких шуток не имеют под собой весомых оснований, применимых к современным версиями IE. А рассказывать о недостатках (с точки зрения сегодняшних подходов и ожиданий) браузеров 10-летней давности я тоже могу, но не вижу в этом никакого практического смысла.
Если вы знаете баги IE9, а лучше IE10 PP2 — если хотите, давайте обсудим ;)
Тем не менее, 90% таких шуток не имеют под собой весомых оснований, применимых к современным версиями IE. А рассказывать о недостатках (с точки зрения сегодняшних подходов и ожиданий) браузеров 10-летней давности я тоже могу, но не вижу в этом никакого практического смысла.
Если вы знаете баги IE9, а лучше IE10 PP2 — если хотите, давайте обсудим ;)
+1
Именно ваше первое предложение и имел ввиду.
0
Браузер всегда асинхронно грузит скрипты, картинки и другие данные. Кому вообще могло прийти в голову загружать данные с сервера синхронно? Ох, уж эти школьники…
-4
Кстати, интересный момент как раз в том, что это не всегда так — с помощью атрибута async браузеру можно сказать, чтобы он грузил скрипты синхронно.
0
О_О
В приведенном ниже примере, скрипт загружается асинхронно. Где нужно использовать волшебный атрибут async?
var script = document.createElement(«script»);
script.src = «mydomain/myscript.js»;
document.body.appendChild(script);
В приведенном ниже примере, скрипт загружается асинхронно. Где нужно использовать волшебный атрибут async?
var script = document.createElement(«script»);
script.src = «mydomain/myscript.js»;
document.body.appendChild(script);
0
Как-то так:
или
Для синхронизации нужно поставить async = false.
<script async src="test.js"></script>
или
var script = document.createElement("script");
script.async = true;
script.src = url;
document.head.appendChild(script);
Для синхронизации нужно поставить async = false.
+1
А в w3c похоже об этом еще не знают. www.w3.org/TR/html4/interact/scripts.html#h-18.2.1
Нужно написать им.
Нужно написать им.
-1
НЛО прилетело и опубликовало эту надпись здесь
Логично. Т.к. нигде не идет речь о html5.
В html5, кстати есть атрибут async dev.w3.org/html5/spec/Overview.html#the-script-element
Вот только никакой синхронной загрузки через async=false нет.
Когда при парсинге страницы встречается <script src=«test.js»></script> браузер запускает отдельный поток чтобы загрузить этот скрипт и продолжает парсинг документа дальше. А вот как только скрипт полностью загрузится, тогда, если есть атрибут async, скрипт будет выполнен немедленно. Если есть атрибут defer — выполнение скрипта будет отложено до полной загрузки страницы. При отсутствии обоих атрибутов действие развивается по первому сценарию (как и в html4).
Так что никакого полшебного async=false нет и быть не может.
В html5, кстати есть атрибут async dev.w3.org/html5/spec/Overview.html#the-script-element
Вот только никакой синхронной загрузки через async=false нет.
Когда при парсинге страницы встречается <script src=«test.js»></script> браузер запускает отдельный поток чтобы загрузить этот скрипт и продолжает парсинг документа дальше. А вот как только скрипт полностью загрузится, тогда, если есть атрибут async, скрипт будет выполнен немедленно. Если есть атрибут defer — выполнение скрипта будет отложено до полной загрузки страницы. При отсутствии обоих атрибутов действие развивается по первому сценарию (как и в html4).
Так что никакого полшебного async=false нет и быть не может.
0
Не совсем, если вы подключаете скрипты динамически, как в вашем примере выше, по умолчанию они загружаются и выполняются асинхронно, форсированное выключение асинхронности заставляет браузер синхронизировать эти процессы.
См. как это работает вот тут: ie.microsoft.com/testdrive/Performance/AsyncScripts/Default.html
См. как это работает вот тут: ie.microsoft.com/testdrive/Performance/AsyncScripts/Default.html
+1
-1
Попробуйте добавлять скрипты динамически ;)
+1
Пробовал. У них тоже async по-умолчанию false.
Кажется, я неправильно понял, думал вы имеете ввиду атрибут тега «async=false», а не свойство dom-элемента в JavaScript. Но даже свойство dom-элемента не имеет смысла ставить в false, так как это значение по-умолчанию. То есть вы не совсем корректно выразились:
Кажется, я неправильно понял, думал вы имеете ввиду атрибут тега «async=false», а не свойство dom-элемента в JavaScript. Но даже свойство dom-элемента не имеет смысла ставить в false, так как это значение по-умолчанию. То есть вы не совсем корректно выразились:
с помощью атрибута async браузеру можно сказать, чтобы он грузил скрипты синхронно.с помощью атрибута async браузеру можно сказать, чтобы он грузил скрипты aсинхронно, иначе он их будет грузить синхронно
0
НЛО прилетело и опубликовало эту надпись здесь
Допустим это так. И что вы этим хотите сказать?
Из вашего примера, я вижу только разную реализацию парсинга/обработки HTML разными браузерами.
Из вашего примера, я вижу только разную реализацию парсинга/обработки HTML разными браузерами.
0
НЛО прилетело и опубликовало эту надпись здесь
Ни один браузер не должен строить DOM, т.к. в скрипте может быть document.write, который изменит весь DOM.
Chrome на момент вызова этой функции не будет содержать ссылки на body и проверить это очень легко:
<source lang=«html>
<!DOCTYPE html>
Да, скрипты не дают рендерить страницу, пока не будут выполнены, хотя все современные браузеры загружают (но не выполняют) их асинхронно. То есть, загружаются — асинхронно, выполняются — синхронно.
Async влияет только на порядок выполнения.
Скрипты, которые подключаются после загрузки страницы блокируют поток выполнения, потому им необходимо указать „async“
И никакого
Chrome на момент вызова этой функции не будет содержать ссылки на body и проверить это очень легко:
<source lang=«html>
<!DOCTYPE html>
document.getElementsByTagName
возвращает Live NodeList. Разница в поведении Фокса и Хрома это всего-лишь разница между дебаггерами. Хромовский рендерит результат когда уже есть, а Фоксовский — во время вызова console.log. Да, скрипты не дают рендерить страницу, пока не будут выполнены, хотя все современные браузеры загружают (но не выполняют) их асинхронно. То есть, загружаются — асинхронно, выполняются — синхронно.
Async влияет только на порядок выполнения.
Скрипты, которые подключаются после загрузки страницы блокируют поток выполнения, потому им необходимо указать „async“
И никакого
async="false"
не существует, он имеет отрицательное значение по-умолчанию.+1
Прошу прощения, вот код:
<!DOCTYPE html>
<head>
<title></title>
<script>
console.log( document.getElementsByTagName('body').length ); // 0
</script>
</head>
<body class="123"></body>
0
НЛО прилетело и опубликовало эту надпись здесь
Да, вот пруф, что по-умолчанию скрипты грузятся асинхронно, но выполняются синхронно:
<!DOCTYPE html>
<head>
<title></title>
<script src="comment.js"></script>
<script src="second.js"></script>
<script> alert( 'async' ) </script>
</head>
comment.js
document.write('<!--');
second.js
alert(2);
second.js
загрузится, но не выполнится. alert( 'async' )
хотя и загрузился раньше, чем comment.js
, но выполнен не был.+1
DOM строится несколько раз за время обработки страницы. Это же дерево, в него можно добавлять и удалять ноды в любое время. Скорее браузер не должен предоставлять доступ скриптам к DOMу до окончания загрузки, но это дело вкуса.
0
Вы стали жертвой заблуждения. Причина — особенность работы консоли в Chrome.
Дело а том, что console.log получая ссылку на объект визуализирует его асинхронно. То есть если вы сделаете console.log(123); то 123 выведется в консоли немедленно, а если сделаете console.log({ a: 2 }), то сначала вставится пустая строка, после чего заменится на интерактивный вьювер. Другой вопрос, что Chrome работает очень быстро и пустую строку заметить сложно. Но измените немного свой скрипт, чтобы это заметить:
Повторите эксперимент с открытой консолью, вы увидите сначала пустую строку, а после отработки второго цикла — массив с <body>.
Так как визуализация по ссылке на объект происходит асинхронно, то состояние объекта отображается не на момент вызова console.log, а на момент визуализации. Визуализация происходит по setTimeout, который в вашем примере отработает после того как отработают все скрипты в синхронном режиме (без атрибута async), то есть уже после того как будет полностью обработан документ (его HTML).
Есть несколько условий, когда может срабатывать визуализация. Например, на это влияют выброс диалоговых окон (alert/confirm/prompt) или вывод через document.write/document.writeln. Попробуйте этот код:
Повторите эксперимент и вы получите пустой «массив».
По факту, document.getElementsByTagName('body') возвращает не массив, а HTMLCollection — то есть объект, потому он и визуализируется асинхронно. Превратите коллекцию в массив и получите ожидаемый результат.
Или же верните первый элемент коллекции, или самостоятельно проинспектируйте document.getElementsByTagName('body') в нужный момент и вы получите тоже ожидаемый результат — пустой список.
Консоль в Firefox (Firebug) работает иначе чем в Сhrome, она визуализирует значения синхронно, то есть показывает фактическое значение в текущий момент, что более накладно по ресурсам, но более полезно для отладки. Сравните результат следующего кода в Chrome и Firefox:
В Chrome в обоих случая будет Object у которого свойство a == 2, а Firebug покажет состояние объекта на момент вызова console.log, будет два разных значения.
Таким образом асинхронностью тут не пахнет. Скрипты могут загружаться асинхронно, но выполняются всегда последовательно (если не используется атрибут async). Пока скрипт не отработал, документ после </script> не пасится, так как в скрипте может появится document.write, который изменит конечный документ.
Дело а том, что console.log получая ссылку на объект визуализирует его асинхронно. То есть если вы сделаете console.log(123); то 123 выведется в консоли немедленно, а если сделаете console.log({ a: 2 }), то сначала вставится пустая строка, после чего заменится на интерактивный вьювер. Другой вопрос, что Chrome работает очень быстро и пустую строку заметить сложно. Но измените немного свой скрипт, чтобы это заметить:
for (i=0;i<100000000;) {i++}
console.log(i);
console.log(document.getElementsByTagName("body"));
for (i=0;i<100000000;) {i++}
Повторите эксперимент с открытой консолью, вы увидите сначала пустую строку, а после отработки второго цикла — массив с <body>.
Так как визуализация по ссылке на объект происходит асинхронно, то состояние объекта отображается не на момент вызова console.log, а на момент визуализации. Визуализация происходит по setTimeout, который в вашем примере отработает после того как отработают все скрипты в синхронном режиме (без атрибута async), то есть уже после того как будет полностью обработан документ (его HTML).
Есть несколько условий, когда может срабатывать визуализация. Например, на это влияют выброс диалоговых окон (alert/confirm/prompt) или вывод через document.write/document.writeln. Попробуйте этот код:
for (i=0;i<100000000;) {i++}
console.log(i);
console.log(document.getElementsByTagName("body"));
alert('!');
Повторите эксперимент и вы получите пустой «массив».
По факту, document.getElementsByTagName('body') возвращает не массив, а HTMLCollection — то есть объект, потому он и визуализируется асинхронно. Превратите коллекцию в массив и получите ожидаемый результат.
for (i=0;i<100000000;) {i++}
console.log(i);
console.log(document.getElementsByTagName("body")); // визуализируется после, содержит <body>
console.log(Array.prototype.slice(document.getElementsByTagName("body"))); // визуализируется сразу - пустой массив
Или же верните первый элемент коллекции, или самостоятельно проинспектируйте document.getElementsByTagName('body') в нужный момент и вы получите тоже ожидаемый результат — пустой список.
for (i=0;i<100000000;) {i++}
console.log(i);
console.log(document.getElementsByTagName("body")[0]); // выведет undefined
alert(document.getElementsByTagName("body").length); // покажет 0
Консоль в Firefox (Firebug) работает иначе чем в Сhrome, она визуализирует значения синхронно, то есть показывает фактическое значение в текущий момент, что более накладно по ресурсам, но более полезно для отладки. Сравните результат следующего кода в Chrome и Firefox:
var x = { a: 1 };
console.log(x);
x.a = 2;
console.log(x);
В Chrome в обоих случая будет Object у которого свойство a == 2, а Firebug покажет состояние объекта на момент вызова console.log, будет два разных значения.
Таким образом асинхронностью тут не пахнет. Скрипты могут загружаться асинхронно, но выполняются всегда последовательно (если не используется атрибут async). Пока скрипт не отработал, документ после </script> не пасится, так как в скрипте может появится document.write, который изменит конечный документ.
+9
Иногда все же нужны синхронные запросы, например когда хочется отправить запрос при закрытии браузера, и желательно, чтоб он уверенно дошел до получателя.
0
Если вы используете другой браузер, скорее всего, вы получите замороженное окно.
Специально проверил. Chrome/Firefox/Opera, никто не виснет.
+8
А вы уверены, что внутри кода правильно поставили адрес на свой тестовый пример?
var sUrl = «http://localhost/hangme.aspx?hang=1&seconds=360»;
var sUrl = «http://localhost/hangme.aspx?hang=1&seconds=360»;
-5
Уверен. Оно даже через некоторое время «Response Received» написало. Не надо считать комментирующих идиотами.
+5
Если вы используете IE9, вы наверняка, заметите, золотистую плашку снизу, предлагающую «Восстановить страницу». Если вы используете другой браузер, скорее всего, вы получите замороженное окно.Пиар IE9 и антипиар других браузеров как всегда лжив, бессмыслен и беспощаден.
+10
Вот выложил этот же пример:
www.kichinsky.ru/hangme.aspx
В момент отправки и до получения ответа интерфейс страницы наглухо виснет.
www.kichinsky.ru/hangme.aspx
В момент отправки и до получения ответа интерфейс страницы наглухо виснет.
0
Мне видео залить на ютуб, где у меня браузер не виснет, или что?
+6
Понимаете, у каждого человека есть какой-то свой внутренний барьер, когда он стремится доказать остальным что он прав и остальные не правы или же пытается выяснить, в чем тут дело, если есть разные точки зрения.
Мне доказывать ничего не надо. Вы можете сказать версии браузеров, я попытаюсь их себе поставить, либо найдутся хабрапользователи с такими версиями, и на практике это либо будет воспроизведено, либо нет.
Дальше мы сделаем совместный вывод, что вполне возможно, что не у всех браузеров поведение абсолютно идентично.
p.s. В любом случае обратите внимание, что 1) это перевод, и 2) не факт, что автор тестировал абсолютно все комбинации всех популярных браузеров.
Мне доказывать ничего не надо. Вы можете сказать версии браузеров, я попытаюсь их себе поставить, либо найдутся хабрапользователи с такими версиями, и на практике это либо будет воспроизведено, либо нет.
Дальше мы сделаем совместный вывод, что вполне возможно, что не у всех браузеров поведение абсолютно идентично.
p.s. В любом случае обратите внимание, что 1) это перевод, и 2) не факт, что автор тестировал абсолютно все комбинации всех популярных браузеров.
-4
не факт, что автор тестировал абсолютно все комбинации всех популярных браузеровТем не менее, весьма категорично заявил, что
Если вы используете другой браузер, скорее всего, вы получите замороженное окно.То есть, попросту соврал.
0
www.youtube.com/watch?v=pZwxlNQvloI
Урезал таймаут до 10 секунд, чтобы 5 минут не писать. Интерфейс не подвисает.
Урезал таймаут до 10 секунд, чтобы 5 минут не писать. Интерфейс не подвисает.
+4
Ок, опытным путем у нас есть два голоса, что Opera под Linux не блокирует интерфейс страницы при синхронных запросах.
Давайте проверим остальные браузеры?
Давайте проверим остальные браузеры?
0
Я тут уже даже в Konqueror проверял — не хочет блокировать и всё тут.
+1
opera действительно не блокирует интерфейс страницы. а вот хром13 и фф6 как и положено замораживают страницу. в хроме даже надпись Request sent не появляется до конца таймаута.
0
В Хроме 13 блокируется вкладка, но девелоперская панель и другие вкладки — работают.
+4
У меня ваш пример даже и в ИЕ не виснет.
0
А так: kichinsky.ru/hangme.aspx?
0
Chromium 12. Область рендеринга вкладки с тестом действительно «подвисает». Всё остальное — живое. Просто для статистики. Видео выкладывать не буду.
0
У вас страница с асинхронными запросами по-разному называется: сначала wont_hangme.aspx, а потом cant_hangme.aspx.
0
Opera 11.10, Linux arch 3.0-ARCH, все отлично.
Наверное я в этой жизни ошибся браузером… и ОС. Этот топик не для меня.
Наверное я в этой жизни ошибся браузером… и ОС. Этот топик не для меня.
-6
Префразирую перевод:
наш браузер иногда зависает из за штатной возможности грузить скрипты синхронно
не используйте синхронную загрузку чтобы наш браузер не зависал.
мы не будем бороться с этим в браузере потому что синхронная загрузка это очень плохо.
Хоть и вполне легальна, и соответствует стандарту.
нам все равно, что другие браузеры такое проблемы не имеют.
еще раз не используйте синхронную загрузку чтобы наш прогрессивный ИЕ9 не зависал.
наш браузер иногда зависает из за штатной возможности грузить скрипты синхронно
не используйте синхронную загрузку чтобы наш браузер не зависал.
мы не будем бороться с этим в браузере потому что синхронная загрузка это очень плохо.
Хоть и вполне легальна, и соответствует стандарту.
нам все равно, что другие браузеры такое проблемы не имеют.
еще раз не используйте синхронную загрузку чтобы наш прогрессивный ИЕ9 не зависал.
+4
Вы хоть поняли суть поста?
0
Потрудитесь перефразировать слово зависания? И расшифруйте мне пожлуйста тогда вот эту фразу
> 8.4% всех зависаний IE9 за прошедший месяц являются следствием того, что XMLHttpRequest объекты блокируют поток UI синхронным запросом.
> 8.4% всех зависаний IE9 за прошедший месяц являются следствием того, что XMLHttpRequest объекты блокируют поток UI синхронным запросом.
+1
Все браузеры (ок, похоже, кроме Оперы), блокируют UI во время синхронных запросов. Заблокированный на долгое время UI — для пользователя и есть зависание страницы. Речь в статье исключительно об этом.
+1
Я наверное не чувствую разницы между, зависания браузера, и зависание вкладки. Насколько мне представляется это немного разные вещи.
Или я что то опять не так понял?
Или я что то опять не так понял?
0
под UI тут подразумевают интерфейс сайта, а не браузера. ну и соответственно зависания тоже сайта, а не браузера.
0
При отправки синхронных запросов, другие элементы на странице не реагируют ни на что пока запрос не выполнится, это и есть «зависание».
+1
Вообще-то ИЕ был первым браузером использующим отдельный процесс для каждой вкладки, так что зависает не браузер, а отдельная вкладка.
+1
А что, еще живы библиотеки, которые позволяют писать XMLHttpRequest-запросы в синхронном стиле? Оо
+6
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Почему вы должны использовать XMLHttpRequest асинхронно