Таймери в javascript (setinterval, settimeout)

У програмуванні на скриптових мовах періодично виникає необхідність створити паузу - призупинити виконання програми на деякий час, а потім продовжити роботу. Наприклад, в сценаріях VBS і PHP можливі такі методи:

VBS: wscript.sleep 1500 (зупинка на 1.5 секунди)

PHP: sleep (10); (Зупинка на 10 секунд)

  1. i = 1;
  2. відкладаємо додавання цифри "1" до поля введення на 0.9 секунди;
  3. негайно за постановкою цієї задачі цикл йде далі: i = 2;
  4. відкладаємо додавання цифри "2" до поля введення на 0.9 секунди;
  5. .

Негайно означає, наприклад, 1 мс (тобто незрівнянно мало, в порівнянні з 900 мс): цикл прозведёт свою роботу практично миттєво, створивши кілька відкладених завдань від однієї і тієї ж точки часу. Це означає, все відкладені завдання по "малювання" будуть виконані практично в один і той же час, без пауз між додаванням нових цифр. Цикл запускається; все завмирає на 0.9 с; і шіррр - все цифри вистрілюються в ряд одна за одною.

А як в подібному випадку правильно застосувати setTimeout. Це складно. Доведеться викликати функцію рекурсивно (зсередини функції ту ж саму функцію), а щоб цей процес не був нескінченним, задати умову зупинки (наприклад, величину друкованого числа):

І ще змінну i доведеться форматувати поза функції - наприклад, так:

Ось тепер все працює, як треба (ми зменшили час затримки з 0.9 с до 0.4 с). Але для подібних завдань логічніше все-таки застосовувати не setTimeout а setInterval (хоча при цьому знадобиться дві функції):

Особливість методу Javascirpt setInterval в тому, що він не проходить «сам собою», його треба зупиняти спеціальним методом clearInterval. А щоб було зрозуміло, що саме зупиняти, задачі по відкладеної дії присвоюються спеціальні ідентифікатор - таймер: window.timer1 = window.setInterval (.).

Ідентифікатори можна привласнювати так само і завданням, створюваним методом setTimeout. Всі ідентифікатори таймерів повинні відрізнятися один від одного (бути унікальними в межах поточного вікна браузера). Тоді можна створити у вікні кілька різних завдань, що використовують відкладені дії, і ці завдання будуть виконуватися паралельно (ніби як одночасно, якщо у комп'ютера вистачає ресурсів), що в принципі неможливо в PHP або VBS.

Випадаюче меню

Наше виїжджає меню - реально виїжджає (з-під «шапки»): між елементами спеціально залишені зазори, щоб бачити, як воно виїжджає. Несподівано виявилося, що ми не можемо зробити однаково плавний виїзд для списків різної довжини - ймовірно, через низьку продуктивність комп'ютера (AMD Athlon 999 МГц).

Досить очевидно, що для краси і гармонії потрібно, щоб списки різних пунктів меню випадали за одне і те ж час. Тобто довші списки повинні випадати з більш високою швидкістю, більш короткі - з меншою швидкістю. Здавалося б, це можна реалізувати так:

  1. Встановлюємо загальний час «виезжанія», наприклад, в 200 мс.
  2. Якщо випадає має висоту 20 px, очевидно, що ми можемо рухати його вниз по одному пікселю за інтервал 10 мс - і тоді за 200 мс список вилізе весь.
  3. Якщо випадає має висоту 40 px, щоб укластися в той же час, ми повинні рухати його вниз по одному пікселю за 5 мс.

Тому більш-менш вирівняти час виезжанія меню можна тільки за допомогою милиць, і ще неясно, як це буде працювати на більш швидкому комп'ютері. Але ж ми повинні розраховувати на найповільніший? Алгоритм (без урахування швидкодії комп'ютера) виходить приблизно такий:

  1. Встановлюємо загальний час виезжанія списку: time = 224 (ms).
  2. Встановлюємо мінімальний час для одного інтервалу в циклі: delay = 3 (ms).
  3. Встановлюємо мінімальний крок для руху списку: offset = 1 (px).
  4. Міняємо все це в залежності від висоти списку: 1) збільшуємо час затримки (інтервалу) обернено пропорційно висоті і прямо пропорційно до загального часу time (при висоті 224 коефіцієнт дорівнює 1); 2) якщо висота більше 40 px, збільшуємо мінімальний крок пропорційно висоті. Константа "40" отримана досвідченим шляхом для найбільш повільного комп'ютера. Тести на комп'ютері Pentium 4 CPU 2.53GHz виявили точно таке ж число - 40. Інакше таймери йдуть розносячи, списки виїжджають не в ногу.

Ось тепер списки більш-менш виїжджають. За більш-менш схоже час. На сторінці setinterval.htm.

Сама функція, що висуває вкладені списки з меню, як бачимо, дуже проста. Залишилося тільки запустити її приблизно такий рядком:

Ну, а перед запуском тільки обчислити всі ці maxtop і offset, а також помістити список в положення mintop. Чим і займається «попередня» функція slide () розміром в 40 рядків. А все разом - в файлі setinterval.js. Так, і ця хрень ні хрена не буде працювати без підключеного файлу стилів menuroll.css.

Схожі статті