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, время: 06:28. |