понеділок, 4 жовтня 2010 р.

Використовуємо таймери для вирішення різних проблем

От є, здавалось би, проста ситуація (JS-ники її добре знають): користувач наводить мишку на елемент А, з'являється елемент Б, користувач може вибрати один з піделементів Б або забрати мишку з А чи Б, передумавши, і Б має зникнути (приклад - випадаюче, контекстне менюменю). Все просто: навішуємо на стейдж маус лісенер і перевіряємо, чи перетинається з А або Б. Ні - ховаєм Б (чому не навішувати на Б лісенер MOUSE_OUT ви самі дідете методом проб і помилок - якщо досі не дійшли).
А якщо А і Б - зовсім окремі об'єкти, які один про одного не мають нічого знати, і А з Б не перетинаються, тому, при переведенні мишки з А на Б, Б закриється? Ну знову все просто: при створенні об'єкта Б не ініціалізуєм лісенер мишки стейджем доти, поки мишка на нього не зайшла. Але тоді відведення мишки з А його не закриє, поки користувач не наведе мишку на Б - це не зручно. Тоді можна в Б встановлювати прапорець, щось типу _canBeClosed=false, при наведенні мишки на Б піднімати його, у лісенері стейджа перевіряти цей прапорець, і додатково в Б, при появі на екрані, запустити таймер (в середньому на 1.5-2 секунди), на його TIMER_COMPLETE теж піднімати цей прапорець.

До речі, всі "випадіючі" елементи додавайте в стейдж - щоб вони завжди перекривали всі інші візуальні елементи і вам не треба було думати, в якій послідовності які елементи були додані на екран і хто кого перекриє. Ну хто вже зовсім не знає - для їх позиціонування використовуйте localToGlobal().

Ще ситуація: є "важка" функція (запит до сервера за тими самими даними), яка має викликатись тільки один раз в один момент часу. А може вона спрацювати на якийсь лісенер, а в проекті івентами плюються всі кому не лінь і розгрібати цю систему нема можливості, або з якихось причин відрубувати користувачу можливість генерувати івенти, які запускають цю функцію - нема. Словом, є у вас ризик подвійного виклику (і бардаку в наслідок цього) і відловити його причину дуже важко (хоч це і потрібно обов'язково зробити), а проблему вирішити треба, і то дуже швидко. Знову-таки, оголошуєься в тому ж класі статичний прапорець, по замовчуванні false, у виклику функції він перевіряється, якщо false - функція виконується, прапорець піднімається і запускається таймер на потрібний для ігнорування всіх наступних викликів цієї функції час, на його TIMER_COMPLETE прапорець знову встановлюється в false.

Ну і, хто ще раптом не знає, як перевіряти швидкість виконання операцій:

var startDate: Date;
var test1Date: Date;
var test2Date: Date;
var str: String;

startDate = new Date();
for(var i: int = 0; i < 100000; i++) {
  str = _function1(args);
}
test1Date = new Date();

for(var j: int = 0; j < 100000; j++) {
  str = _function2(args);
}
test2Date = new Date();

trace(test1Date.time - startDate.time, test2Date.time - test1Date.time);

Тільки не використовуйте в середині циклів trace - його обробка всіми плагінами, які його ловлять, може давати похибку.

Немає коментарів:

Дописати коментар