setTimeout/setInterval - неожиданное поведение
Всем доброго времени суток...
IE8\HTML+JS+ActiveX ; Страничка с согласия юзверя работает через объекты ActiveX c MS Excel и файловой системой, а пока она это делает, я хотел бы показывать некую анимацию, пусть банально менять текст в <textarea>... Вычитав, что о многопоточности говорить не приходится, начал копать в сторону асинхронности, и вот я "раскуриваю" setTimeout/setInterval реф которых утверждает что они предназначены для асинхронного вызова функций, казалось бы "то что надо!", а нет... или я не уловил суть (хотя с асинхронностью знаком не по наслышке на серверном Node.js) так вот... пуcть в теле документа имеем некую функцию myStatusBar() , она у нас занимается некой анимацией (добавляет точку к <textarea>*.value) - setInterval(function(){myStatusBar();},500); далее собственно запускаем наш тяжеловесный процесс работы с Excel и файловой системой назовем его myHeavyProcess()(это или последовательный вызов нескольких функций, или вызов одной, которая сама вызывает все последующие //PS: в средем 5-6 сек.) вот что у нас вышло setInterval(function(){myStatusBar();},500); myHeavyProcess(); что ожидалось: функция myStatusBar() будет выполняться каждые 0,5 сек. в то время как будет выполняться myHeavyProcess() что вышло: функция myStatusBar() выполнится один раз, потом будет "шурупить" myHeavyProcess() все свои 5-6 сек. без какой либо анимации, и как только она закончит опять выполнится myStatusBar()... Ну и какая-же это асинхронность ? |
Цитата:
|
Ладно, вот так...
setInterval(function(){myStatusBar();},500); setTimeout(function(){myHeavyProcess();},1000); на выходе то-же самое... |
Я уверен, что я где-то недопонимаю "евангелия" клиентского программирования...
Передо мной стоит задача рисовать анимацию пока выполняются сложные расчеты и взаимодействия, подскажите что мне для этого надо сделать? |
setTimeout/setInterval не создают новый процесс, код выполняется в том же процессе, но с задержкой. Соответственно, если процесс занят, то ничего другое выполниться не сможет.
Цитата:
|
Цитата:
или переписывайте код с шагами,как сказал Kolyaj |
Web Workers - заманчиво, а самое главное НАДО (я пока не столкнулся с "клиенто-шаманизмом" думал, что таки есть нечто подобное уже давно)
но к сожалению в "осле" который мне требо в связи с ActiveX, даже наметок для Web Workers нет, есть правда эмулятор но это в общем-то костыли :)) Я решил так: добавлю к прототипу функции метод вызывающий функцию ответственную за всю анимацию на страничке, ну и собственно, разбивать код на более мелкие фрагменты, между которыми "взывать" к анимации... PS: косяк в том, что это тяжело сделать равномерно. |
И все равно анимации не выходит...
Даже если я линейно в программу повтыкал вызов функции которая рисует анимацию, никаких таймаутов и прочего - все линейно... Все равно... то есть то нет... такое чувство, что она не успевает отрисовываться что-ли... ну в чем может быть дело ? Cмысл такой: есть некий element пусть <textarea id='satus'>Здесь хочу писать статус выполнения</textarea> ну делаю банально myAnimation('выполняется myFunction1') myFunction1() myAnimation('выполняется myFunction2') myFunction2() myAnimation('выполняется myFunction3') myFunction3() myAnimation('выполняется myFunction4') myFunction4() myAnimation('выполняется myFunction5') myFunction5() myAnimation('выполняется myFunction6') myFunction6() myAnimation('Готово') function myAnimation(text){ var element = document.getElementById("status"); element.value = text }; //все myFunction*() это какие ни будь вычисления/манипуляции с объектами ActiveX вешаем все это на button и понеслась... все myFunction*() успешно выполняются одна за одной... а вот в 'satus' отрисовывается только 'выполняется myFunction1'... и висит, потом когда все расчеты закончились быстро мелькает 'выполняется myFunction6' и 'Готово' В чем дело... как заставить отрисовываться в обязательном порядке ? |
Цитата:
|
как быть ?
|
Каждую следующую myFunction вызывать через setTimeout
|
здесь представлен список свойств обращение к которым вызывает немедленный redraw элемента:
1. offsetTop, offsetLeft, offsetWidth, offsetHeight, 2. scrollTop/Left/Width/Height, 3. clientTop/Left/Width/Height, 4. getComputedStyle() или currentStyle в IE. ...фактически в IE8 100% работают только 1-ые... На одном из англ.форумов вычитал Цитата:
|
Цитата:
Дело было в баге самого IE : пока идет непосредственная работа с COM-компонентами в моем случае ActiveX, IE для повышения производительности отключает все вcтроенные redraw / reflow... хочешь что-то отрисовать - вызывай его принудительно. ("как?" - постом выше) |
И так окончательная точка
JavaScript у клиента в данный момент (не берем в расчет Web Workers которые еще "будующее") не выполняется асинхронно никак. setTimeout и setInterval - вопреки рефу, псевдоасинхронность т.е. управление не совмещает выполнение кодов разных функций за один такт... |
Цитата:
|
********************
|
Цитата:
а ассинхронность(в браузерном JS) - явление строго однопоточное. ассинхронность позволяет положить функции в очередь, до наступления события, когда они смогут выполниться. При этом они вовсе не обязаные выполнятся одновременно, и даже не гарантируется что они выполнятся в указанном вами порядке(в случае когда они должны сработать "одноврменно"). |
Вам как JavaScript-ерам должна быть знакома технология серверного JavaScript - NODE.js, вот здесь часть идеологии асинхронности...
Более того, не хотел бы с вами спорить, но видимо вы заблуждаетесь... Цитата:
Т.е. по наступлению события или таймера, исполнение текущего контекста приостанавливается, и исполняется контекст назначенный, после чего возобновляется выполнение текущего... В нашем-же случае setTimeout и setInterval являются таймерами, но они не останавливают выполнение основного контекста, а покорно ждут пока контекст исполнится... |
Цитата:
Цитата:
|
вот некий код для "разбора полетов"
<html> <head> </head> <body> <script type="text/javascript"> AsyncTest() function AsyncTest(){ var someText = '' setInterval(function(){someText = someText + '-AsyncInjection-';}, 12) for(var i = 0; i < 20; i++){ someText = someText + '-MainTheadInjection-' }; alert(someText) } </script> </body> <html> что-же увидите на выходе ? Цитата:
Цитата:
проведите аналогичный эксперимент в NODE.js :) |
Цитата:
если: Цитата:
Вот оф.реф для setInterval Цитата:
|
var t = Date.now(); var str = ''; for(var i = 0; i<20; i++) { str +='afa'; } alert(Date.now()-t); |
Цитата:
|
и... :)
мне alert-нуло '0' это вы к чему ? где тут асинхронность и вообще инструкция в 6-ой строке листинга 'str' это что ? |
Цитата:
Цитата:
|
Цитата:
setTimeout(foo, 500); bar(); Допустим функция bar выполняется 2 секунды. Тогда вопреки вашему желанию функция foo выполнится не через пол секунды, а через две, когда освободится поток. В общем случае запись setTimeout(foo, n) означает "запустить функцию foo не раньше чем через n миллисекунд", а не "запустить функцию foo через n миллисекунд". |
PS: :) кстати по поводу NODE.js я погорячился setTimeout и setInterval работают точно так-же ... виноват... зато callback-и прерывают выполнение как и ожидается
var events = require("events"); var emitter = new events.EventEmitter; // создаём генератор var someText = ''; // задаём обработчик пользовательского события "event1" emitter.on("event1", function(data) { if(){} someText = someText + '-Async-' }); for(var i = 0; i < 20; i++){ someText = someText + '-MainThead-'; emitter.emit("event1"); } console.log(someText) ... PPS: Вы безусловно правы ВСЕ... вы описываете реальное положение вещей. НО ЭТО НЕ АСИНХРОННОСТЬ ! Нельзя функцию с отложенным вызовом называть асинхронной. Это просто функция с отложенным вызовом и не более того. Асинхронно - это не синхронно... то есть код будет выполняться в одном потоке но в смешанном режиме, по крайней мере такова асинхронность в низкоуровневом программировании. когда выполнение двух функции (func1 и func2) в асинхронном режиме выглядит как-то так: Выполняется инструкция из func1 Выполняется инструкция из func2 Выполняется инструкция из func1 Выполняется инструкция из func2 Выполняется инструкция из func2 Выполняется инструкция из func1 и т.д. (правила скрещивания обусловлены платформой, ресурсами под инструкцию и т.д.) они не паралельны, но и не синхронны... они асинхронны. Здесь-же мы наблюдаем псевдоасинхронность... |
Цитата:
|
|
Давайте по порядку. Асинхронная функция -- такая функция, которая сразу передаёт управление вызвавшему её коду, но продолжает в это время что-то делать и результат своей работы сообщает позже. Разумеется, продолжает что-то делать она в другом потоке, но этот другой поток реализован или на уровне платформы (XMLHttpRequest в браузере), или на уровне ОС (i/o в NodeJS). Сам JavaScript при этом остаётся однопоточным.
В случае использования setTimeout второй поток не нужен. Функция ничего не делает, пока ждёт запуска переданной в setTimeout функции, а ничего не делать можно и в одном потоке :) |
Цитата:
:agree: Я действительно увлекся спором, не обладая достаточной базой для его поддержания... хотя в итоге - "В JavaScript не исполняется асинхронно, как не крути" с чего собственно все и началось :yes: |
function time(){
setTimeout(time,500); //Запускаем интервал func(); //Запускаем другую функцию } Это тебе о чем нибудь говорит? |
Часовой пояс GMT +3, время: 11:41. |