Удалить прослушиватель с анонимной функцией в ActionScript 3

up.addEventListener(MouseEvent.CLICK, 
    function clickFunc(event:MouseEvent):void
    { 
        revealSpinner(event,51.42,1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);
down.addEventListener(MouseEvent.CLICK, 
    function clickFunc(event:MouseEvent):void
    { 
        revealSpinner(event,51.42,-1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);

Вышеприведенный код добавляет слушателя к нескольким MC. Первоначально методы были анонимными, но я назвал их clickFunc(), чтобы попытаться ссылаться на них в моем удаленном прослушивателе.

Вот мой код прослушивателя. Оба этих фрагмента находятся в отдельных функциях. Метод add listener вызывается перед методом удаления.

up.removeEventListener(MouseEvent.CLICK, clickFunc );
down.removeEventListener(MouseEvent.CLICK, clickFunc);

Как только я публикую фильм, я получаю эту ошибку:

1120: Access of undefined property clickFunc.

Ответ 1

Прежде всего, вы используете одно и то же имя, которое используется дважды (clickFunc), не может быть выведено, к которому вы ссылаетесь в своих вызовах removeEventListener. Во-вторых, clickFunc будет доступен только в функции, где он объявлен:

function foo() {
    var clickFunc: Function;
    up.addEventListener(MouseEvent.CLICK, 
        clickFunc = function (event:MouseEvent):void
        { 
            revealSpinner(event,51.42,1,spinner);
            event.currentTarget.removeEventListener(event.type, arguments.callee);
            autoTimer.stop();
        },
        false, 0, true);

    // 'clickFunc' available here, so this is possible:
    up.removeEventListener(MouseEvent.CLICK, clickFunc);
}

function bar() {
    // 'clickFunc' is not available here, so this is not possible:
    up.removeEventListener(MouseEvent.CLICK, clickFunc);
    // 1120: Access of undefined property clickFunc
}

Если вам нужно ссылаться на методы (например, удаляя их из события), они не могут быть анонимными. Если вам нужно ссылаться на них из нескольких методов, они не должны быть локальными для одного метода (foo в приведенном выше примере). И им нужны разные идентификаторы (clickFunc1 и clickFunc2, если хотите). Это мое рекомендуемое решение:

private function addHandlers(): void
{
    up.addEventListener(MouseEvent.CLICK, upClickHandler, false, 0, true);
    down.addEventListener(MouseEvent.CLICK, downClickHandler, false, 0, true);
}

private function removeHandlers(): void
{
    up.removeEventListener(MouseEvent.CLICK, upClickHandler);
    down.removeEventListener(MouseEvent.CLICK, downClickHandler);
}

private function upClickHandler(event:MouseEvent):void
{ 
    revealSpinner(event,51.42,1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}

private function downClickHandler(event:MouseEvent):void
{ 
    revealSpinner(event,51.42,-1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}

Конечно, если, как и в вашем примере, методы идентичны, вы можете использовать только один:

private function addHandlers(): void
{
    up.addEventListener(MouseEvent.CLICK, clickHandler, false, 0, true);
    down.addEventListener(MouseEvent.CLICK, clickHandler, false, 0, true);
}

private function removeHandlers(): void
{
    up.removeEventListener(MouseEvent.CLICK, clickHandler);
    down.removeEventListener(MouseEvent.CLICK, clickHandler);
}

private function clickHandler(event:MouseEvent):void
{ 
    revealSpinner(event,51.42,-1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}

Ответ 2

ok есть несколько способов, которыми вы можете это сделать. вот первый способ, который я думаю, это то, что вы ищете.

var upAnon:Function;
var downAnon:Function;

up.addEventListener(MouseEvent.CLICK, 
    upAnon = function (event:MouseEvent):void
    { 
        revealSpinner(event,51.42,1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);
down.addEventListener(MouseEvent.CLICK, 
    downAnon = function (event:MouseEvent):void
    { 
        revealSpinner(event,51.42,-1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);

up.removeEventListener(MouseEvent.CLICK, upAnon);
down.removeEventListener(MouseEvent.CLICK, downAnon);

и вот еще один способ: получить тот же желаемый эффект и функциональность, что и первый. просто более чистая и обычно стандартная практика.

function upFunction(event.MouseEvent):void {
    revealSpinner(event,51.42,1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}
function downFunction(event.MouseEvent):void {
    revealSpinner(event,51.42,-1,spinner);
    event.currentTarget.removeEventListener(event.type, arguments.callee);
    autoTimer.stop();
}

up.addEventListener(MouseEvent.CLICK, upFunction, false, 0, true);
down.addEventListener(MouseEvent.CLICK, downFunction, false, 0, true);

up.removeEventListener(MouseEvent.CLICK, upFunction);
down.removeEventListener(MouseEvent.CLICK, downFunction);

Причина, по которой вы будете использовать первый тип, заключается в том, что вы создаете eventHandler внутри функции и должны использовать переменные, определенные в этой функции, внутри вашей анонимной функции. например, здесь я получаю доступ к var countMe внутри функции anon и увеличивая его на mouse_down, и он будет увеличиваться до тех пор, пока не будет активирована mouse_up. поэтому каждый раз, когда я нажимаю вниз, он будет отсчитывать от 0 до мыши, а затем начнется.

var anonFunc:Function;

function doThisStuff(event:MouseEvent):void {
    var countMe = 0;

    stage.addEventListener(Event.ENTER_FRAME,
        anonFunc = function (e:Event) {
            countMe++;
            trace(countMe);
        }
    );  
}

function stopCounting(event:MouseEvent):void {
    stage.removeEventListener(Event.ENTER_FRAME, anonFunc);
}

stage.addEventListener(MouseEvent.MOUSE_DOWN, doThisStuff);
stage.addEventListener(MouseEvent.MOUSE_UP, stopCounting);

Ответ 3

Этот должен работать... просто удалите имя метода...

 up.addEventListener(MouseEvent.CLICK, 
        function(event:MouseEvent):void
        { 
            revealSpinner(event,51.42,1,spinner);
            event.currentTarget.removeEventListener(event.type, arguments.callee);
            autoTimer.stop();
        },
        false, 0, true);
    down.addEventListener(MouseEvent.CLICK, 
        function(event:MouseEvent):void
        { 
            revealSpinner(event,51.42,-1,spinner);
            event.currentTarget.removeEventListener(event.type, arguments.callee);
            autoTimer.stop();
        },
        false, 0, true);

Ответ 4

Вы создаете обработчики событий со слабыми ссылками (передавая true для этого последнего параметра). Как вы, наверное, уже знаете, слабая ссылка не помешает сборщику мусора собирать вашу функцию. Однако, если вы не поддерживаете ссылку на свои обработчики событий вне области функции, в которой вы их определяете (не похожа на вас), у обработчиков будет только одна слабая ссылка, чтобы сохранить их в живых, сборщик мусора работает, ваши обработчики в любом случае ушли. Суть в том, что обработчики событий не выглядят так, как будто они срабатывают после запуска мусора, поэтому беспокоиться об удалении обработчиков несколько бессмысленно. Они сами уйдут, независимо от того, хотите вы их или нет.

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

Ответ 5

попробуйте следующее:

up.addEventListener(MouseEvent.CLICK, 
    clickFunc = function(event:MouseEvent):void
    { 
        revealSpinner(event,51.42,1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);

down.addEventListener(MouseEvent.CLICK, 
    clickFunc = function(event:MouseEvent):void
    { 
        revealSpinner(event,51.42,-1,spinner);
        event.currentTarget.removeEventListener(event.type, arguments.callee);
        autoTimer.stop();
    },
    false, 0, true);