Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   [Алгоритмы] Возможно ли улучшить событийную систему? (http://www.flasher.ru/forum/showthread.php?t=215609)

robotR2D2 12.06.2018 06:46

Возможно ли улучшить событийную систему?
 
Я думаю, ни для кого не секрет, что событийная система содержит серьезный изъян - она не гарантирует распространение событий в той очередности, в которой они были испущены в коде.
Код AS3:

        var s:Sprite = new Sprite();
        s.name = "Parent";
        s.addEventListener(Event.ADDED, this._onAdded);
 
        var schSprite:Sprite = new Sprite();
        sch.name = "Child";
        sch.addEventListener(Event.ADDED, this._onChildAdded);
        s.addChild(sch);
 
        __________________________________
 
        function _onAdded(e:Event):void {
                var s:Sprite = e.target as Sprite;
                trace(e.type, s.name);
        }
 
        function _onChildAdded(e:Event):void {
                s.removeEventListener(e.type, this._onChildAdded);
 
                var s:Sprite = e.target as Sprite;
                var s2:Sprite = new Sprite();
                s2.name = "subChild";
                s.addChild(s2);
        }
 
        //output:
        //added, subChild
        //added, Child

Таким образом наверх (да и внутри объекта, испустившего событие) прилетают события абы как. Для связанных событий - это может быть критично. Например, может прилететь "removed" вперед "added".
Да, зная, что событийная модель несовершенна, можно городить кучу проверок или, там где возможно, заранее выстраивать операции особым образом. Но меня интересует возможен ли фикс этого?

Создаю событийную систему для моделей. Прикинул варианты:
1) В функции "dispathEvent" событие добавляется в глобальную очередь, и продолжается распространение события первого в очереди.
Цитата:

Плюс: в коде дальше "dispatchEvent" можно рассчитывать на то, что событие распространилось.
Минус: не гарантируется, что первичные получатели события его обработали ДО того, как событие прилетело к следующим.
Минус очень жирный...

2) Вместо "dispatchEvent" использовать "addToDispatchQueue(event:Event, callback:Function)".
Цитата:

Плюс: события распространяются в той последовательности, в которой были испущены; обрабатываются полностью каждым участником в цепи.
Минус: собственник события не знает, когда его событие распространится и вынужден подписать callback на случай, если ему нужно выполнить действия после фактического распространения события.
3) Продолжать мириться с существующей системой
4) Ваш вариант

ZergMaster 12.06.2018 09:45

Я делал CommandManager, в котором просто есть стэк команд, без всяких событий... Получается, что и callback особо не нужен, так как команде просто передается экземпляр "собственника события" (в числе прочих необходимых) и на .exec производятся все необходимые манипуляции.
Вообще, события не очень люблю.. Стараюсь использовать только когда это реально оправданно преимуществами баблинга, например.

undefined 12.06.2018 10:48

Насколько я помню события приходят в том порядке, в котором добовлялись слушатели т.е. путаница может случиться только если у тебя added и removed имеют одинаковый type что маловероятно. Можно минимальный пример когда события приходят не в том порядке?

Tails 12.06.2018 10:52

4 аргумент - priority:
https://help.adobe.com/en_US/FlashPl...ventListener()

Обычно таких зависимых событий немного, этого вполне хватает.

Zebestov 12.06.2018 11:24

В приведенном примере события отправляются совершенно упорядоченно: от самого вложенного (первое) до самого наружного (последнее).

Единственное, что приходится разруливать (я делал это... никогда) — это обработка одного и того же события от одного и того же объекта разными слушателями. В этом случае поможет комментарий от Tails.

robotR2D2 12.06.2018 15:36

@ZergMaster, без минималистического примера - сложно понять. Что именно гарантирует, что во время выполнения одного стэка команд, не будет выполнен промежуточный стэк команд?

Цитата:

Сообщение от undefined (Сообщение 1205559)
Насколько я помню события приходят в том порядке, в котором добовлялись слушатели

Цитата:

Сообщение от Tails (Сообщение 1205560)
4 аргумент - priority

от порядка добавления слушателей порядок распространения событий (во множественном числе) не зависит вообще никак.

Цитата:

Сообщение от undefined (Сообщение 1205559)
Можно минимальный пример когда события приходят не в том порядке?

А чем пример в первом посте не угодил? Есть родитель, который сперва получает событие добавленного "внука", а потом событие добавленного "сына". Да, родитель знает, что добавляет ребенка по addChild, но если в цепь добавить "деда", то у него поедет крыша, ведь сперва он узнает, что у него есть "правнук", а уже потом узнает, что есть "внук". Мне кажется - это не нормально.

Цитата:

Сообщение от Zebestov (Сообщение 1205562)
В приведенном примере события отправляются совершенно упорядоченно: от самого вложенного (первое) до самого наружного (последнее).

Так-то оно так, но почему это считается нормальным? (если отмести сам факт того, что реализацию flash event system никак не исправить)
Если я сказал собеседнику две фразы, я ожидаю, что сперва он услышит первую фразу, а затем вторую. Однако событийная система такова, что к слушателю "фразы" прилетают рандомно. Это как читать книгу, предложения в которой перемешаны в случайном порядке.

Приведу пример, есть контроллер, который создает зеркальную иерархию от существующей иерархии. Он слушает BaseModel. Казалось бы, по "added" он создает зеркало-"узел" и крепит его к зеркало-родителю, ссылка на которого есть у event.target.parent (модель-эталон). Но проблема в том, что у parent - может не быть этой ссылки на зеркало, ведь он еще сам не имеет зеркального узла, потому что внутри addChild был вызван еще один addChild (в обработчике события "added").

Таким образом, я должен, понимая, что событийная система имеет изъян, искать в цепи parent первую "отзеркаленную" модельку и выстраивать иерархию от нее. Это же вынуждает меня проверять, а не был ли event.target "отзеркален" в предыдущем обработчике. Более того, в контроллер может прилететь другое важное событие от модельки (которое было испущено в ее обработчике "added") тогда как она сама еще не имеет зеркало, что существенно.

Я понимаю, что можно не испускать событий в обработчике "added" и не добавлять детей там же. Но речь не про самоограничения, а про работу событий так, как это должно быть с точки зрения здравого смысла.

СлаваRa 12.06.2018 16:52

Цитата:

Таким образом, я должен, понимая, что событийная система имеет изъян...
Событийная модель работает как положено, а вот ваша "архитектура" "хочет" что-то под себя

undefined 12.06.2018 17:12

Цитата:

от порядка добавления слушателей порядок распространения событий (во множественном числе) не зависит вообще никак.
Ой ли
Код AS3:

mc.addEventListener(MouseEvent.CLICK,onClick1,false);
mc.addEventListener(MouseEvent.CLICK,onClick2,false);
function onClick1(e:MouseEvent):void {
        trace("handler 1");
}
function onClick2(e:MouseEvent):void {
        trace("handler 2");
}

имеем в консоле
handler 1
handler 2

НО
Код AS3:

mc.addEventListener(MouseEvent.CLICK,onClick2,false);
mc.addEventListener(MouseEvent.CLICK,onClick1,false);
function onClick1(e:MouseEvent):void {
        trace("handler 1");
}
function onClick2(e:MouseEvent):void {
        trace("handler 2");
}

имеем в консоле
handler 2
handler 1

Для разруливания таких ситуаций и нужен параметр priority:
Код AS3:

mc.addEventListener(MouseEvent.CLICK,onClick2,false,0);
mc.addEventListener(MouseEvent.CLICK,onClick1,false,1);
function onClick1(e:MouseEvent):void {
        trace("handler 1");
}
function onClick2(e:MouseEvent):void {
        trace("handler 2");
}

Снова имеем
handler 1
handler 2
т.к. у onClick1 приоритет больше чем у onClick2

У тебя налицо непонимание event flow.
UI события идут от корня(stage) до элемента их испустившего(capture phase),после этого событие начинает "всплывать",двигаясь от ребенка назад к корню(bubbling phase).По дефолту ты ловишь события в фазе всплытия потому у тебя и путаница.Если нужно ловить события в capture phase используй 3-ий параметр у addEventListener.

robotR2D2 12.06.2018 17:52

Цитата:

Сообщение от СлаваRa (Сообщение 1205564)
Событийная модель работает как положено, а вот ваша "архитектура" "хочет" что-то под себя

Событийная модель работает так, как ее запрограммировали. Для сравнения в as3 "дед" всегда получит событие "added" правнука, даже если в процессе события удалится одно из звений цепи parent'ов (видимо, в момент испускания события создается массив со всеми parent'ами вплоть до stage), а в том же OpenFl (собирал под другой язык) - "дед" получит только "removed".
Моя архитектура не хочет ничего того, что не естественно. Для простоты освоения программирования к нему нередко приводят параллели с реальностью. Вот и я хочу, чтобы моя первая сказанная фраза всегда была услышана первой, а не как придется.
Акцентирую, я не утверждаю, что текущие события никуда не годятся. Я ищу вариант улучшения, если он возможен.

@undefined, теряюсь, что сказать. Я знаю, как работает priority... Если вы потратите чуть больше времени, чем "беглый взгляд", на изучение кода в первом посте, а так же на пример с "дедом" и "правнуком"/"внуком" позже - вы поймете, что я спрашиваю кардинально о другом.

undefined 12.06.2018 18:22

Цитата:

@undefined, теряюсь, что сказать. Я знаю, как работает priority...
Ну ты видишь что порядок добавления слушателей таки влияет на порядок их вызова?


Часовой пояс GMT +4, время: 13:43.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.