Модераторы: Sardar, Aliance

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> И всетаки Sleep! Как организовать задержку на JavaScript 
:(
    Опции темы
Иль
Дата 30.7.2005, 11:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 544
Регистрация: 3.3.2005
Где: Москва

Репутация: 2
Всего: 14



Наткнулся и вспомнил
http://forum.vingrad.ru/index.php?showtopic=59796

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

Работает он без тормозов:
1. Реализуем свой Sleep, который запускается по событию или при вызове из кода sleep(1500). Делает он всего-то, что выкидывает флаг в к-либо глобальной переменной, что якобы он запущен, а потом выставляет тайминг, который запустит его же через заданное время для снятия sleep. Или можно как для моего отладчика подвесить на определенное событие пользователя, например любая реализация кнопки "Продолжить" на экране, тк браузер не виснет.
2. Далее во все функции и обработчики вызываемые напрямую (обработчики событий, функции попадающие в тайминги) вставляется проверка на этот флаг. Причем это можно сделать только для нужных для подвешивания событий и функций. Если sleep запущен, то вызывающий контент попавшей в период действия sleep функции кидается в самодельный стек на массиве, а сама функция прерывается не приступив к своей логике. Кидаются не только параметры функций, но и, конечно же, event и this. ИМХО для сохранения лучше использовать Closures - вложенное определение function(){...}
Соответственно флагом, для большей безглючности, можно временно блокировать особо замороченные события пользователя напрочь.
3. По окончании задержки или по onunload страницы Sleep раскручивает стек запуская попорядку функции с их же контентом. Еще я параноидально добавил проверку на исчезновение к-либо части контента на странице, чтоб не споткнутся, на getElementById().

Встает, конэшно, вопрос, как там будет, ведь в неподвешенном браузере можно скролить и ресайзить страницу. Какие там позиции вернет target smile ?

Вот как-то так

Это сообщение отредактировал(а) Иль - 30.7.2005, 11:21


--------------------
Ты виндусятник?... А я да. smile
PM MAIL ICQ Skype GTalk   Вверх
Sardar
Дата 31.7.2005, 16:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

Репутация: 78
Всего: 317



Так, во первых хорошо бы кода немного, а то пример не ясен smile

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

А тепер помечтаем smile

Пусть в JS(экий новый браузер, сказавший хрен! всякой совместимости с NN/IE, либо какое нибудь другое автоматизационное окружение) у нас есть два системных обьекта:
  • Thread - поток иполнения
  • FunctionCallStack - стек вызовов функций
Треды прямо как в Java, прога работает пока есть хотя бы один не "демоновский" тред. Тред создаёться с переданной функцией-делегатом:
Код
var t=new Thread("my thread", function() {
 my_object.run();
});
t.start(); //запуск треда, заметим что метода stop() нет, код треда должен сам выйти из функции.
//из глобального обьекта Thread.listActive() можно полуцить список всех активных тредов

Треды сами реализуют sleep/yield/wait/notify.

Обьект FunctionCallStack интересен для "хака" JS, этот обьект отображает стек вызовов текущего треда. Также он позволяет менять обратные адреса функций! На этом можно делать блоки на уровне одного треда например. Как это может работать:

Код

//первый вызов прерываемой функции
inter_func();

//мы в какой нибудь функции вызываем 
my_sleep();
//............

function my_sleep() {
  var ret_func=FunctionCallStack.top(); //обьект отвечающий за "нативный" адрес в опкодах функции, т.н. снепшот
  alert("Мы пришли из функции: "+ret_func.getFunction()); //может быть anonymous если из анонимной функции(обработчик события).
  //note: возвращаеться обьект Function, а не строка :)
  //также вызваються методы обьектов, вообщем как делегаты в C#
  if(my_ret) { //если прерываемая функция оставляла свой снепшот
     my_ret_adres_flag=true; //ставим для неё флаг
     FunctionCallStack.call(my_ret);
     //наша прерываемая функция возобновиться, отработает и мы вернёмся в эту точку
  }
  return; //снепшот предидущей функции снимаеться и возвращаеться
}

//пример прерывания и ворзврата
function inter_func() {
  alert("Выполнение этой функции прервём, а потом возвратимся");
  var ret_adres=FunctionCallStack.takeSnapshot("my_label"); //обьект снепшот
  //внимание, все лейблы это внутренние свойства функций, интерпретатор найдёт лейбл и возьмёт его адрес
  //иначе даст ошибку "лейбл не найден". Естественно что напрямую адрес задать нельзя =)
  //Другими словами поиск лейбла ведёться на этапе исполнения, хотя хорошо бы дело слинковать на этапе компиляции
  setMySnapshot(ret_adres); //отдаём кому нибудь этот снепшот
  my_label: //метка, сейчас поддерживаетсья только в циклах, с неё продолжиться выполнение
  if(my_ret_adres_flag) { //если кто то установил флаг, что выполнение можно продолжать
     //то делаем что нибудь, например рендерим инфу, что загружалась
  }
  return;
}

Мудрённо? Я тоже так думаю smile Поэтому тредов хватает. Но иногда так хочеться поиграть со стеком вызовов, потому хорошо бы иметь такую фичу.


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
Иль
Дата 1.8.2005, 16:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 544
Регистрация: 3.3.2005
Где: Москва

Репутация: 2
Всего: 14



Код дам когда вернусь к теме, надо ж отладку еще сделать, пока только скупые идеи smile

А вот с такой точки зрения: Реально, есть клиентская сторона и в ней полюбэ разрешен только JS. Ждать многопоточность, а с ней, видимо, и управление тредами в JS не приходится, тк даже если это появится, то пройдет туева хуча времени, пока умрет старое семейство бродилок. Да еще много раз кто-то призадумается, а зачем это простому WEB-девелоперу. Есть только одно: "Хочу - значит могу", от этого и пляшу smile

В JS халява с возвратом к адресу усыпленного потока понятно не катит, поэтому нужно придумать что-то, как придумали для наших однопоточных процессоров.

Насколько я понял себя и других участников форума поднимающих вопрос о Sleep, то Sleep нужен не простой, а реализующий в условиях однопоточности логическую многопоточность (многозадачность). Так уж получилось меня занесло в эту степь, поэтому основываясь на опыте выложил идею. Т.е. надо-то чтоб зафиксировались состояния экрана или его части, а также выбранная часть объектной модель JS (DOM и так отдался в руки JS smile и повиснет, никуда не денется). Можно не все фиксить, а выбранные участки. Например, делаем, чтоб экран или его область не изменялись какое-то время или до срабатывания определенного разрешенного события. В тоже время мы позволяем изменять разрешенные ноды, допускаем разрешенные события и скрипты.

Забыл тогда сказать про setInterval. Если он используется и вызывает неразрешенную в периоде Sleep функцию (изменяющую состояния), то нужно предусматривать несложное управление и им/ими (приостановка и возобновление из стека), а иначе на маленьких интервалах задержек может получится, что он забьет вызываемой функцией самодельный стек, а это никчему и может даже подвесить.

Буду пока зреть до имплементации smile


--------------------
Ты виндусятник?... А я да. smile
PM MAIL ICQ Skype GTalk   Вверх
Sardar
Дата 1.8.2005, 17:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

Репутация: 78
Всего: 317



Э не, подобные блокировки будут не только сложными в реализации, но и громоздкими и не удоными в использовании, если я тебя правильно понял.

На мой взгля лучший подход это многопотоковость + синхронизация как в Java. Мы обьявляем любой обьект в блок synchronized(обьект) и все кто попытаються использовать этот обьект уснут, пока мы не снимим блокировку(не выйдем из блока). Этот механизм наиболее популярен, от низкоуровнего программирования(семафоры/защищённые зоны), до Java/C#, где каждый обьект обладает своим «счётчиком»(семафором).

В результате имеем два треда:

Код
(new Thread("thread1", thr1)).start();
(new Thread("thread2", thr2)).start();

function thr1() {
  var n=document.getElementById("node_id");
  //треды исполнаяються "одновременно", потому не хотим что бы нода внезапно менялась
  synchronized(n) {
    //что то делаем с нодой, точно знаем что кроме этого треда никто её не использует
  } //при выходе из блока семафор освобождаеться
}

function thr2() {
  while(true) { //чрез каждую секунду меняем цвет ноды
    var n=document.getElementById("node_id");
    n.style.color=Color.randomColor(); //в этом месте уснём если на ноду подняли семафор
    Thread.currentThread().sleep(1000);
  }
}


Таким "дедовским" методом можно гибко управлять потоками и блокировать доступ.


P.S. Что то я часто мечатать начал... smile


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
Иль
Дата 1.8.2005, 17:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 544
Регистрация: 3.3.2005
Где: Москва

Репутация: 2
Всего: 14



Не ждать же имплементации.
Цитата(Sardar @ 1.8.2005, 17:12)
Э не, подобные блокировки будут не только сложными в реализации, но и громоздкими и не удоными в использовании!

Ну и напрасненько, у меня геморойчик рулит прекрасненько smile
В смысле подобное

Не соглашусь. Чего там сложного-то? Ну нету у нас конструкторов и деструктуров, но жить-то надо. Всего-то на одну строчку в каждом обработчике больше, да + реализация логики стека. Не чувствую ни глючности, ни громозкости, ни неудобства. Наоборот, комфортно, удобно, а главное сухо smile

Да не, ну чего я буду доказывать без сорца на руках


--------------------
Ты виндусятник?... А я да. smile
PM MAIL ICQ Skype GTalk   Вверх
Иль
Дата 2.8.2005, 17:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 544
Регистрация: 3.3.2005
Где: Москва

Репутация: 2
Всего: 14



Подумал и правда был неправ, это требует возьни. Я ж забыл, что по уму надо реализовать как-то чтоб Sleep умел останавливать в середине функции, а не только обрывать вызываемые после остановки. Это, ИМХО, потребует больше логики.
Я б тогда применил останов через встраиваемую функцию с сохранением контента через Closures
Код

if(Sleep(function(){...так_по_идеи_передаем_контент_прерываемой...}))// Sleep() вернет true если нужно прервать функцию в этом месте
    return;
// МАРКЕР №4

Не додумал как, но по идеи при раскрутке стека надо вернуться к месту "// МАРКЕР №4" и продолжить со старым контентом с него. Может через eval, может динамически менять тело функции с восстановлением потом, может раздуть код и реализовать прыжок к маркеру??? Решений несколько, но какое универсальное?
Вопросов больше чем ответов, особенно пока не возьмешься за написание кода.
Это пока на стадии мыслей и во что выльется и получится ли...
Поторопился


--------------------
Ты виндусятник?... А я да. smile
PM MAIL ICQ Skype GTalk   Вверх
Sardar
Дата 3.8.2005, 01:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бегун
****


Профиль
Группа: Модератор
Сообщений: 6986
Регистрация: 19.4.2002
Где: Нидерланды, Groni ngen

Репутация: 78
Всего: 317



Похоже выход только один, вкладывать анонимные функции:

Код

function test() {
//что нибудь делаем
window.setTimeout(function() {
  //продолжаем что либо делать после паузы
  window.setTimeout(function() {
    //ещё одна пауза
    //делаем что нибудь полезное
  }, 1000);//вторая пауза 1 секунда
},3000); //первая пауза 3 секунды
}

Но повторяю лучше поменять логику. Нельзя на JS программить в стиле паскаля или C, точно также с такими вещами не програмят в функциональных языках.

Код при работе будет хавать память, постоянно создавая новые анонимные функции, хранящие контекст вызова.


--------------------
 Опыт - сын ошибок трудных  © А. С. Пушкин
 Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik
 Оценить мои качества можно тут.
PM   Вверх
Aliance
Дата 15.8.2005, 20:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


I ♥ <script>
****


Профиль
Группа: Модератор
Сообщений: 6418
Регистрация: 2.8.2004
Где: spb

Репутация: 55
Всего: 137



Иль
Если правильно понял, то маркер о котором ты говорил можно применять так (только в циклах for и инструкциях switch)
Код

marker:
   for (var i = 0; i < 5; i++) {
      sub-marker:
         for (var j = 0; j < 5; j++) {
            if (j > 3) break; // Выход из самого внутреннего цикла
            if (i == 2) break marker; // то же самое
            if (i == 4) break sub-marker; // выход из внешнего цикла
         }
   }


Это сообщение отредактировал(а) Aliance - 15.8.2005, 20:58
PM MAIL WWW ICQ Skype   Вверх
Ответ в темуСоздание новой темы Создание опроса
Форум для вопросов, которые имеются в справочниках, но их поиск вызвал затруднения, или для разработчика требуется совет или просьба отыскать ошибку. Напоминаем: 1) чётко формулируйте вопрос, 2) приведите пример того, что уже сделано, 3) укажите явно, нужен работающий пример или подсказка о том, где найти информацию.
 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | JavaScript: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1194 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.