Асинхронность в JavaScript
Цитата:
<div id="box"></div> <script type="text/javascript"> setTimeout(function(){ var dv = document.getElementById('box'); dv.innerHTML += 'Если есть асинхронность, я появлюсь первым.<br />'; }, 100); a = new Date(); while( ( ( new Date() ) - a ) <= 200 ) {} var dv = document.getElementById('box'); dv.innerHTML += 'Если есть асинхронность, я появлюсь вторым.<br />'; </script> |
devote, а AJAX назван так для красоты?
|
или просто так назван опыт использования шаблона observer (наблюдатель)
|
Цитата:
|
опять некорректный пример с асинхронностью...
|
Согласен с float,
пример не корректный абсолютно.Есть асинхронность а есть порядок выполнения событий в очереди. в аяксе используется и асинхронность и очередь.И пример приведённый демонстрирует очередь а не асинхронность . |
Цитата:
|
Цитата:
|
Цитата:
|
Цитата:
Цитата:
|
Цитата:
devote, первый пример у вас какой-то бредовый. Почему то, что в setTimeout должно появиться первым? Что вы вообще под асинхронностью понимаете? |
Цитата:
|
Причём здесь реализация чего бы то ни было в других языках, и причём здесь что-то, что является дурным тоном в других языках? Как это влияет на JavaScript? И как это всё связано с асинхронностью в JavaScript?
|
Никак, это был ответ на вопрос что я понимаю под асинхроностью
|
Я не увидел в вашем сообщении чего-то похожего на "асинхронность -- это ..."
|
Ну это ваши проблемы, я мыслю на более низком уровне. Тоесть на том на котором все обрабатывает интерпретатор этого JavaScript. Асинхронность это лишь реализация отдельного независимого процесса, который может выполнять свои собственные задачи не влияя при этом на другие процессы, затем при передаче/обмене данных процессы синхронизируются и обмениваются данными. Что вы понимаете под этим словом, известно только вам. Асинхронность это не выполнение AJAX запросов, это просто процесс работает асинхронно, в отдельном процессе/нити.
|
Подозреваю фраза
Цитата:
Хотя, может еще воркерсы где они есть или костыльная замена через postmessage. |
Цитата:
|
Код под NodeJS можно считать асинхронным веб-приложением. Не одним клиентом едины.
|
devote,
Цитата:
Для простоты понимания можно просто назвать асинхронность событийно-ориентированным программированием (event-driven, если хотите), поскольку это определение точнее передает суть. В JavaScript асинхронность представлена в первую очередь таймерами (setTimeout/setInterval), которые не являются "независимыми процессами", а просто отложенными событиями с обработчиком, ну и конечно реализацию работы во всем "внешним" из JavaScript. В случае браузера это BOM, DOM (обработка событий браузера и HTML) и реализацией объекта XMLHttpRequest, а также многих других. В том же Node.js работа со всеми отдельными модулями (БД, программы, чтение файлов) происходит асинхронно. Но асинхронный код может быть написан не только с использованием обмена данных с "внешними" объектами. По сути любой код с обработчиками событий и генерацией событий может быть назван асинхронным, даже если весь код выполняется в одном потоке, как это происходит в JavaScript. Т.е. даже при самостоятельной организации событий и обработчиком код будет асинхронным, поскольку в нем работает правило "установка обработчика - получение сигнала о событии - выполнение обработчика". Поскольку асинхронно не значит "одновременно", и в общем виде не значит, что исполнение кода может быть продолжено, если не завершился участок, названный "асинхронным". Это лишь значит, что через модель событий выполнение кода может быть мягко прервано при наступлении события и будет выполнен обработчик со своим scope. |
Вот, в качестве примера, реализация асинхронного кода на основе собственных событий и использования функции setTimeout:
// Скрипт для работы событий: var Ev = { "__listeners__": {}, "EventEmitter": function(object) { object.__listeners__ = {}; object.addEventListener = object.on = this.addEventListener; object.removeEventListener = this.removeEventListener; object.getEventListeners = this.getEventListeners; object.clearEventListeners = this.clearEventListeners; object.emit = this.emit; }, "addEventListener": function(eventName, listener) { eventName in this.__listeners__ ? this.__listeners__[eventName].push(listener) : this.__listeners__[eventName] = [listener]; return listener; }, "removeEventListener": function(eventName, listener) { if (eventName in this.__listeners__) { for (var i in this.__listeners__[eventName]) if (this.__listeners__[eventName].hasOwnProperty(i)) if (this.__listeners__[eventName][i] === listener) this.__listeners__[eventName].splice(i, 1); } }, "getEventListeners": function(eventName) { if (eventName in this.__listeners__) return this.__listeners__[eventName]; return null; }, "emit": function(eventName, eventData) { var self = this; eventData = eventData || null; if (eventName in this.__listeners__) { for (var i in this.__listeners__[eventName]) if (this.__listeners__[eventName].hasOwnProperty(i)) { setTimeout((function(i) { return function() { self.__listeners__[eventName][i](eventData); } })(i), 0); } } } }; // Какой-то конструктор: var B = function() { // Добавляем методы событий в наш объект: Ev.EventEmitter(this); // Подписываемся тремя обработчиками на событие "someEvent": this.addEventListener("someEvent", function() { alert(2); }); this.addEventListener("someEvent", function() { alert(3); }); this.addEventListener("someEvent", function() { alert(4); }); }; // Этот метод генерирует событие "someEvent": B.prototype.generateEvent = function() { alert("Let's start!"); // Генерируем событие: this.emit("someEvent"); // Проверяем, остались ли мы в этом участке кода: alert(1); // Если первым будет выведено alert(1), значит мы работаем асинхронно, поскольку вызов // метода emit произошел, но код обработчика не выполнился последовательно. Затормозим // выполнение на 3 секунды для точной проверки: var n = new Date(); while(new Date() - n < 3000) {}; // Только теперь должно быть выполнение асинхронных обработчиков. }; // Создаем объект и выполняем метод, генерирующий событие: b = new B(); b.generateEvent(); |
Цитата:
Цитата:
|
dmitriymar,
В общем виде асинхронность не значит одновременное выполнение кода. Это всего лишь не последовательное выполнение кода, основанное (чаще всего) на событиях. Просто тот же самый msdn может запутать программиста, поскольку для увеличения скорости работы асинхронных методов, в .NET реализация обработчиков асинхронных вызовов и событий сделана в отдельном потоке и асинхронность просто скрывает части реализации многопоточности для программиста, но как уже было сказано, это не обязательное условие. Цитата:
Просто из-за "обычных" примеров асинхронности в JavaScript происходит путаница. Асинхронность событий DOM не в том, что пользователь может стать источником события в любое время, а то, что в потоке JavaScript выполнение кода может быть прервано при выходе из текущего scope и выполнится обработчик этого события. Соответственно и для XHR - асинхронность не в том, что мы сделали вызов и он выполняется в то время, когда мы выполняем другой код, а в том, что при наступлении события (смена статуса, получение данных) будут вызваны соответствующие обработчики, даже если они будут выполнены в основном потоке выполнения. |
Цитата:
|
dmitriymar,
Цитата:
Да и даже в этом примере не гарантируется последовательная очередь выполнения обработчиков, они могут быть выполнены в произвольном порядке. Те же события DOM обрабатываются идентично тому, как обрабатывается событие в примере, на самом деле. Именно в том, что обработчик будет вызван "между" вызовами других обработчиков и заключается асинхронность. Если в клиентском коде это не так очевидно, то в Node.js, где главный источник множества событий это web-сервер, это просматривается куда лучше. Поскольку после вызова emit из моего примера может быть обработан другой клиент, например. |
Цитата:
Цитата:
пример из жизни -очередь на оплату допустим комунальных люди из очереди платят синхронно или асинхронно-кто когда захочет или могут оплатить когда кассир отсутствует?(выпоняется другие действия кассиром аналогия с выполнением кода вызвавшим событие) а вот добавление и убывание людей из очереди-асинхронно- никто не дожидается события какогото чтоб стать в очередь да и чтоб выйти из неё не обязательно выполнить оплатить комуналку-но такого нет в языке- соответственно выполнение очереди в языке синхронно Кассир -это js -он синхронен или асинхронен? Я думаю что всё таки синхронен. когда нет других задач обслуживает очередь. когда и очереди нет ничего не делает если нет других задач. а асинхронный аякс-можно сравнить с помощником кассира ,какой принёс платёж и положил его на стол ,а кассир его обработает когда до него очередь дойдёт. P.S. может мне написать книгу раскраску JS для малышей.для детей от 7 до 9 лет?))) |
dmitriymar,
Если между вызовами могут быть обработаны другие события, какая же это синхронность? Была бы синхронность, если бы был прямой вызов, а не обернутый в таймаут. И в этом примере порядок может быть произвольным. Например у меня алерты выскакивают 1, 2, 3, 4; 1, 3, 2, 4; и так далее. |
dmitriymar,
То, что вы описываете, это многопоточность. Если рассматривать асинхронность на примере очереди, то лучше уж так: Люди пришли в офис и получили номерки от 1 до N. Работает одно окно (но где-то может работать два окна), из которого людей вызывают по номеру. При этом в зависит все не только от готовности документов в окне, но и от самих людей в очереди, например, вызвали 3его номера, работают с ним, тут подошли в документы для 14, вызвали его, когда закончили с ним по результатам стали готовы документы для 4ого, вызвали 4ого, после которого стали готовы документы для 8ого и вызвали его, потом документов нет какое-то время, потом пришел документ 5ого, работали с ним, и так далее и тому подобное. |
Цитата:
|
Цитата:
Пример конечно спорен но всёже. |
Асинхронность не в том, как работает "кассир" (однопоточность или многопоточность), а как устроена сама очередь и как из неё вызываются люди.
|
Цитата:
а пример с таймутами -поставишь ты на первый задержку минуту,на второй секунду. сработает второй первым-что здесь асинхронного? здесь как раз синхронность-он в очереди стоит раньше первого. а то что накрутить можно-поставить первому минуту второму секунду,и исполнять ещё участок кода вызвавший их две минуты -и говорить что очередь в этом случае асинхронная -так это называется по другому-руки не из того места ростут |
Асинхронное формирование потока выполнения. Не стек. Все согласны?
Хотя я даже не понимаю о чем вы спорите, любой человек видит разницу между тем же асинхронным и синхронным ajax, да и при работе с DOM тоже всё кристально ясно. Больше похоже на флуд или крючкотворство. |
dmitriymar,
Я если честно не понимаю, чего вы не поняли и почему утверждаете про синхронность исходя из однопоточности JavaScript, учитывая сколько в этом обсуждении уже написано про это. Представьте мой пример в таком виде, есть объект и сложное UI, модель которого связана через события с нулевым таймаутом при emit. От пользователя приходят два события, которые имеют сложную обработку, допустим это будет mouseover и mousedown. Допустим, что они произошли практически одновременно. В синхронном коде обработчик mouseover будет выполняться до конца, после этого будет вызван обработчик mousedown. При организации кода через события с асинхронным выполнением произойдет mouseover, будет получен из кода emit, потом обработан mousedown, будет получен emit, потом обработчики, если они будут генерировать новые события и передавать управление с нулевым таймаутом, будут выполняться не последовательно, а в режиме вытесняющей очереди со случайным выбором. Дальнейшие разъяснения нужны? Для подтверждения моих слов вот вам код. Если бы было все синхронно и просто очередью, до обработчики бы были вызваны в порядке, что алерты были бы такие: 1, 2, 4, 6, 3, 5, 7. Но они будут вызваны в таком порядке: 1, 2, 3, 4, 5, 6, 7. Потому что вызов события не мешает выполнению как-бы другого рута событий. Поправьте, если я ошибаюсь и это тоже "синхронная" работа: // Скрипт для работы событий: var Ev = { "__listeners__": {}, "EventEmitter": function(object) { object.__listeners__ = {}; object.addEventListener = object.on = this.addEventListener; object.removeEventListener = this.removeEventListener; object.getEventListeners = this.getEventListeners; object.clearEventListeners = this.clearEventListeners; object.emit = this.emit; }, "addEventListener": function(eventName, listener) { eventName in this.__listeners__ ? this.__listeners__[eventName].push(listener) : this.__listeners__[eventName] = [listener]; return listener; }, "removeEventListener": function(eventName, listener) { if (eventName in this.__listeners__) { for (var i in this.__listeners__[eventName]) if (this.__listeners__[eventName].hasOwnProperty(i)) if (this.__listeners__[eventName][i] === listener) this.__listeners__[eventName].splice(i, 1); } }, "getEventListeners": function(eventName) { if (eventName in this.__listeners__) return this.__listeners__[eventName]; return null; }, "emit": function(eventName, eventData) { var self = this; eventData = eventData || null; if (eventName in this.__listeners__) { for (var i in this.__listeners__[eventName]) if (this.__listeners__[eventName].hasOwnProperty(i)) { setTimeout((function(i) { return function() { self.__listeners__[eventName][i](eventData); } })(i), 0); } } } }; // Какой-то конструктор: var B = function() { var self = this; // Добавляем методы событий в наш объект: Ev.EventEmitter(this); // Подписываемся тремя обработчиками на событие "someEvent": this.addEventListener("someEvent", function() { self.emit("someEvent2"); alert(2); }); this.addEventListener("someEvent", function() { self.emit("someEvent3"); alert(3); }); this.addEventListener("someEvent2", function() { self.emit("someEvent4"); alert(4); }); this.addEventListener("someEvent3", function() { self.emit("someEvent5"); alert(5); }); this.addEventListener("someEvent4", function() { alert(6); }); this.addEventListener("someEvent5", function() { alert(7); }); }; // Этот метод генерирует событие "someEvent": B.prototype.generateEvent = function() { alert("Let's start!"); // Генерируем событие: this.emit("someEvent"); // Проверяем, остались ли мы в этом участке кода: alert(1); // Только теперь должно быть выполнение асинхронных обработчиков. return false; }; // Создаем объект и выполняем метод, генерирующий событие: b = new B(); b.generateEvent(); |
dmitriymar, если асинхронность - характеристика процессов, не совпадающих по времени, то:
<p id="foo">0</p> <script> var src = "http://fc06.deviantart.net/fs41/i/2009/051/9/3/CIA_LOGO_by_krumbi.jpg?" + Math.random(); document.write('<img src="' + src + '" height="300" width="300" />'); function init(element) { if(document.getElementById(element) !== null) { foo(); } else { setTimeout(function() { init(element); }, 0); } } function foo() { var i = 0; return function() { if (i++ < 25) { document.getElementById('foo').innerHTML = Math.random(); } else i = 0; setTimeout(arguments.callee, 100); }(); } init('foo'); </script> можно ли этот пример назвать асинхронным? |
Цитата:
|
monolithed,
Ну здесь мешанка нтмл и скрипт. здесь изначально два потока-поток загрузки нтмл и поток скрипта. асинхронность также можно привести в пример при загрузке скриптов из разных субдоменов-типа грузятся параллельно и выполнится тот какой первым загрузится не дожидаясь загрузки того какой первым указан ,при условии что первым загрузился второй. Но и это не будет асинхронным выполнением скрипта-поскольку пользуется многопоточность браузера. и последний когда загрузится он дождётся когда отработает первый загрузившийся и только тогда начнёт работу-произойдёт "синхронизация" в итоге |
dmitriymar,
Вы говорите глупости, если честно. Очередь не синхронная. Попробуйте сами поставить 100 нулевых таймаутов и в это время словить событие клика на странице. Оно будет поймано и выполнится, вытесняя эти таймауты. Попробуйте ловить все события мыши, события mousedown, mouseup, click если вы будете часто нажимать на кнопку могут смешаться, и может получится очередь выполнения обработчиков mousedown, mousedown, mouseup, mouseup, click, click. Да и вообще, если используется setTimeout, который откладывает выполнение функции на событие таймаута, пускай и нулевого, это уже асинхронность. Потому что вызвали в одном месте, выполнился в другом при определенном событии (в конкретном случае - при выходе из текущей области видимости). В асинхронности о "синхронизации" речи быть не может, это возможно только в многопоточности, когда мы можем повесить поток в ожидании ответа от другого потока. Асинхронность просто (в большинстве случаев) заключается в том, что мы можем установить коллбек, который может быть вызван при наступлении определенного события. Либо отложить выполнение кода по таймауту. Жалко только то, что сама по себе асинхронность, как и функции setTimeout/setInterval не являются частями какого-либо связанного с JavaScript стандарта. Так получается, что справедливо иметь несколько точек зрения на такой, казалось бы, очевидный вопрос. |
Цитата:
1 очередь выполняется последовательно 2 новые события могут ставиться не в конец очереди.-зависит и от браузеров и от событий какие уже в ней,задержки в тех же таймаутах. 3 при этом очередь с поставленными в неё событиями будет выполнятся от начала до конца последовательно 4 очередь по размеру ограниченна. 5 . 0 в таймауте может трактоваться как выполнить сразу так и выполнить минимальной задержкой в некоторых браузерах до 30 м.с. -зависит от браузера. Итого ситуация стоит 10 таймаутов с задержкой в 30 м.с. и если произойдёт событие то оно может стать как до них,так после них,так и между ними. Не стоит то,что рендомно возводить в систему,и рассматривать очередь как стек и на основе этого строить теории Формирование очереди асинхронно с исполняемым кодом,но вот выполнение очереди всегда будет последовательно. действия будут выполняться в зависимости от того как они расположены в очереди. И причём здесь синхронность/асиинхронность-если изначально сказал что пример не корректен и работает согласно последовательности очереди и взаимодействия с очередью и не может быть примером асинхронности |
|
Часовой пояс GMT +3, время: 16:41. |