Как стать автором
Обновить

Комментарии 86

а почему бы не разнести UI и исполнение js по разным потокам?
Потому что в большинстве случае вы скорее хотите синхронизации: короткое, почти незаметное для пользователя блокирование UI на время каких-нибудь манипуляций с интерфейсом, вроде обновления элементов через DOM.

Ну и в целом, писать в синхронном режиме проще. Для асинхронного выполнения JS будут веб-воркеры, но они не всемогущи :)
я говорю с позиции разработчика браузеров — отрисовка UI в своём потоке, исполнение js — в своём.
Это потребует не только введения дополнительной синхронизации (то есть усложнения браузера), но и пересмотра принципов разработки приложений.
JS изменяет DOM, Рендерер берёт данные из DOM. Зачем переделывать архитектуру приложений?

Единственное, чего это потребует, это поднять задницу с шезлонга на Мальдивах и написать нормальный браузер. Это невозможно.
Расскажите, пожалуйста,
1) как вы будете сихнронизировать между собой потоки js и ui и реагировать на все изменения в одном или другом и, в частности в dom?

2) в каких нормальных браузерах поток UI полностью отделен от потока JS и вычислительные задержки в JS не приводят к замораживанию интерфейса?

p.s. На всякий случай: веб-воркеры как предлагают отделение кода на js в отдельный поток, но этот поток не умеет взаимодействовать с UI (DOM).
1) Колбеки? Зачем рендереру знать о том, что происходит в JS?
2) В ФФ вроде бы собираются вводить. Да и вообще, многопоточность — тренд. В нормальных браузерах, в отличии от IE, почему то нет этих 9% зависаний.

ЗЫ: Анекдот.
-Папа, а что такое мультизадачность Windows?
-Погоди, сынок, сейчас дискетку доформатирую и покажу.
1. А это не проблема рендерера. Это проблема того, кто занимается синхронизацией изменений в DOM, рендеринга, операций в JS и реакцией на действия пользователя с UI.

2. Как это нет? Вы пробовали код в Firefox, Chrome или Safari?
Сейчас тренд это асинхронность а не многопоточность. Многопоточность тренд предыдущего десятилетия.
И что?
А что вы хотите услышать в ответ на свой вопрос?
Может он имел ввиду, что пора бы уже переписать 90% кода, оставшихся с IE5? :)
Может, сквозные баги исчезнут. Правда, появятся новые, но ничего, хотя бы какое-то веселье вирусописателям будет.
Давайте конкретнее про 90% кода, оставшихся с IE5, и сквозные баги, ага?
Если смайлик для Вас уже просто знак препинания, извините. Это была шутка. Однако в каждой шутке есть доля правды.

Про баги IE писать не буду, погуглите. В конце концов, даже Bing гуглит. :)
Смайлик и есть что-то вроде знака препинания ;)

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

Если вы знаете баги IE9, а лучше IE10 PP2 — если хотите, давайте обсудим ;)
Именно ваше первое предложение и имел ввиду.
Браузер всегда асинхронно грузит скрипты, картинки и другие данные. Кому вообще могло прийти в голову загружать данные с сервера синхронно? Ох, уж эти школьники…
Кстати, интересный момент как раз в том, что это не всегда так — с помощью атрибута async браузеру можно сказать, чтобы он грузил скрипты синхронно.
О_О
В приведенном ниже примере, скрипт загружается асинхронно. Где нужно использовать волшебный атрибут async?
var script = document.createElement(«script»);
script.src = «mydomain/myscript.js»;
document.body.appendChild(script);
Как-то так:
<script async src="test.js"></script>


или

var script = document.createElement("script");
script.async = true;
script.src = url;
document.head.appendChild(script);


Для синхронизации нужно поставить async = false.
НЛО прилетело и опубликовало эту надпись здесь
Логично. Т.к. нигде не идет речь о 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 нет и быть не может.
Не совсем, если вы подключаете скрипты динамически, как в вашем примере выше, по умолчанию они загружаются и выполняются асинхронно, форсированное выключение асинхронности заставляет браузер синхронизировать эти процессы.

См. как это работает вот тут: ie.microsoft.com/testdrive/Performance/AsyncScripts/Default.html
Попробуйте добавлять скрипты динамически ;)
Пробовал. У них тоже async по-умолчанию false.
Кажется, я неправильно понял, думал вы имеете ввиду атрибут тега «async=false», а не свойство dom-элемента в JavaScript. Но даже свойство dom-элемента не имеет смысла ставить в false, так как это значение по-умолчанию. То есть вы не совсем корректно выразились:
с помощью атрибута async браузеру можно сказать, чтобы он грузил скрипты синхронно.
с помощью атрибута async браузеру можно сказать, чтобы он грузил скрипты aсинхронно, иначе он их будет грузить синхронно
Попробуйте в консоли создать скрипт
var script = document.createElement("script");</script>

и посмотреть, чему равно async. 
Да, вы правы. Есть ли браузеры, у которых это поведение отлично? Я точно помню, что мне приходилось вручную выставлять async=false.
*приходилось вручную выставлять async=true
Не уверен, насколько я вижу, Chrome, Firefox и IE10PP2 работают тут одинаково. Safari и Opera, вроде, async не поддерживают.
НЛО прилетело и опубликовало эту надпись здесь
Допустим это так. И что вы этим хотите сказать?
Из вашего примера, я вижу только разную реализацию парсинга/обработки HTML разными браузерами.
НЛО прилетело и опубликовало эту надпись здесь
Ни один браузер не должен строить DOM, т.к. в скрипте может быть document.write, который изменит весь DOM.
Chrome на момент вызова этой функции не будет содержать ссылки на body и проверить это очень легко:
<source lang=«html>
<!DOCTYPE html>






document.getElementsByTagName возвращает Live NodeList. Разница в поведении Фокса и Хрома это всего-лишь разница между дебаггерами. Хромовский рендерит результат когда уже есть, а Фоксовский — во время вызова console.log.

Да, скрипты не дают рендерить страницу, пока не будут выполнены, хотя все современные браузеры загружают (но не выполняют) их асинхронно. То есть, загружаются — асинхронно, выполняются — синхронно.

Async влияет только на порядок выполнения.

Скрипты, которые подключаются после загрузки страницы блокируют поток выполнения, потому им необходимо указать „async“

И никакого async="false" не существует, он имеет отрицательное значение по-умолчанию.
Прошу прощения, вот код:
<!DOCTYPE html>
<head>
	<title></title>
	<script>
		console.log( document.getElementsByTagName('body').length ); // 0
	</script>
</head>
<body class="123"></body>
НЛО прилетело и опубликовало эту надпись здесь
Да, вот пруф, что по-умолчанию скрипты грузятся асинхронно, но выполняются синхронно:
<!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, но выполнен не был.
DOM строится несколько раз за время обработки страницы. Это же дерево, в него можно добавлять и удалять ноды в любое время. Скорее браузер не должен предоставлять доступ скриптам к DOMу до окончания загрузки, но это дело вкуса.
Вы стали жертвой заблуждения. Причина — особенность работы консоли в Chrome.
Дело а том, что 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, который изменит конечный документ.
Иногда все же нужны синхронные запросы, например когда хочется отправить запрос при закрытии браузера, и желательно, чтоб он уверенно дошел до получателя.
Тогда нужно хотя бы ставить корректный timeout, чтобы интерфейс пользователя не зависал ;)
Если вы используете другой браузер, скорее всего, вы получите замороженное окно.

Специально проверил. Chrome/Firefox/Opera, никто не виснет.
А вы уверены, что внутри кода правильно поставили адрес на свой тестовый пример?

var sUrl = «http://localhost/hangme.aspx?hang=1&seconds=360»;
Уверен. Оно даже через некоторое время «Response Received» написало. Не надо считать комментирующих идиотами.
Если вы используете IE9, вы наверняка, заметите, золотистую плашку снизу, предлагающую «Восстановить страницу». Если вы используете другой браузер, скорее всего, вы получите замороженное окно.
Пиар IE9 и антипиар других браузеров как всегда лжив, бессмыслен и беспощаден.
Не надо грязи ;)
Ничего личного, обычное наблюдение ^.^
Вот выложил этот же пример:
www.kichinsky.ru/hangme.aspx

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

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

Дальше мы сделаем совместный вывод, что вполне возможно, что не у всех браузеров поведение абсолютно идентично.

p.s. В любом случае обратите внимание, что 1) это перевод, и 2) не факт, что автор тестировал абсолютно все комбинации всех популярных браузеров.
не факт, что автор тестировал абсолютно все комбинации всех популярных браузеров
Тем не менее, весьма категорично заявил, что
Если вы используете другой браузер, скорее всего, вы получите замороженное окно.
То есть, попросту соврал.
Извините, но, по-моему, это вы черезчур категорично воспринимаете предложение с явным предположением («скорее всего») — оригинале:

If you’re using another browser, you’ve probably got a ghosted window.
www.youtube.com/watch?v=pZwxlNQvloI
Урезал таймаут до 10 секунд, чтобы 5 минут не писать. Интерфейс не подвисает.
Ок, опытным путем у нас есть два голоса, что Opera под Linux не блокирует интерфейс страницы при синхронных запросах.

Давайте проверим остальные браузеры?
Я тут уже даже в Konqueror проверял — не хочет блокировать и всё тут.
Ок, у нас есть еще один голос за то, что Konqueror не блокирует UI.
opera действительно не блокирует интерфейс страницы. а вот хром13 и фф6 как и положено замораживают страницу. в хроме даже надпись Request sent не появляется до конца таймаута.
В Хроме 13 блокируется вкладка, но девелоперская панель и другие вкладки — работают.
А в пятом Фоксе даже появилась надпись «request sent», интерфейс остался работоспособным.
Правильно, речь в статье — об интерфейсе внутри страницы. А браузеры, понятное дело, должны изолировать интерфейс (процесс) браузера от содержимого страницы.
И в чём вопрос? Все браузеры ведут себя одинаково — они не отрисовывают ничего внутри вкладки, пока не кончится запрос.
Я не вижу никакого вопроса ;) Вы все правильно сказали.
У меня ваш пример даже и в ИЕ не виснет.
Так работает. В Опере и ФФ выводит Request Sent, после чего виснет вкладка.
Chromium 12. Область рендеринга вкладки с тестом действительно «подвисает». Всё остальное — живое. Просто для статистики. Видео выкладывать не буду.
У вас страница с асинхронными запросами по-разному называется: сначала wont_hangme.aspx, а потом cant_hangme.aspx.
Спасибо! Поправил.
Opera 11.10, Linux arch 3.0-ARCH, все отлично.
Наверное я в этой жизни ошибся браузером… и ОС. Этот топик не для меня.
ОС тут не причем. ну а опера всегда была сама по себе:)
Ага, но наехать нужно было на все браузеры, куда же без этого евангелистам Microsoft.
Во всем нужно видеть наезды, куда же без этого троллям на хабре.
Префразирую перевод:

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

мы не будем бороться с этим в браузере потому что синхронная загрузка это очень плохо.
Хоть и вполне легальна, и соответствует стандарту.

нам все равно, что другие браузеры такое проблемы не имеют.
еще раз не используйте синхронную загрузку чтобы наш прогрессивный ИЕ9 не зависал.

Вы хоть поняли суть поста?
Потрудитесь перефразировать слово зависания? И расшифруйте мне пожлуйста тогда вот эту фразу

> 8.4% всех зависаний IE9 за прошедший месяц являются следствием того, что XMLHttpRequest объекты блокируют поток UI синхронным запросом.
Все браузеры (ок, похоже, кроме Оперы), блокируют UI во время синхронных запросов. Заблокированный на долгое время UI — для пользователя и есть зависание страницы. Речь в статье исключительно об этом.
Я наверное не чувствую разницы между, зависания браузера, и зависание вкладки. Насколько мне представляется это немного разные вещи.
Или я что то опять не так понял?
под UI тут подразумевают интерфейс сайта, а не браузера. ну и соответственно зависания тоже сайта, а не браузера.
Простите фраза
> 8.4% всех зависаний IE9 за прошедший месяц

как бы немного о другом?
не точный перевод, в оригинале: «8,4% зависаний в ИЕ9»
Поправил, чтобы было более очевидно.
При отправки синхронных запросов, другие элементы на странице не реагируют ни на что пока запрос не выполнится, это и есть «зависание».
Вообще-то ИЕ был первым браузером использующим отдельный процесс для каждой вкладки, так что зависает не браузер, а отдельная вкладка.
А что, еще живы библиотеки, которые позволяют писать XMLHttpRequest-запросы в синхронном стиле? Оо
НЛО прилетело и опубликовало эту надпись здесь
Зарегистрируйтесь на Хабре, чтобы оставить комментарий