清除 FileReference 对象上的事件监听器

发布于 2024-09-06 06:41:01 字数 1227 浏览 3 评论 0原文

我有一个奇怪的问题!我试图通过调用函数来删除 FileReference 对象上的事件侦听器,但它似乎没有被删除,我不明白为什么。

这是代码:

private function clearFileUploadListeners(file:FileReference, index:String):void {
    var dispatchEvent:Function = function(event:Event):void {
        dispatch(event.type, event, index);
    };

    file.removeEventListener(Event.COMPLETE, dispatchEvent);
    var bool:Boolean = file.hasEventListener(Event.COMPLETE);
    if (bool)
        trace("ERROR");
}

当我运行此代码时,跟踪实际上发生了。当我试图删除上面的 eventListener 时,我不明白为什么这个布尔值返回 true!我想我可能做了一些非常愚蠢的事情,因为这看起来像是一个奇怪的错误。

我希望有人能在这个问题上帮助我。

编辑:

我相信这与我添加监听器时在另一个函数中定义dispatchEvent函数有关:

private function upload(file:FileReference, index:String):void {
    var dispatchEvent:Function = function(event:Event):void {
        dispatch(event.type, event, index);
    };

    file.addEventListener(Event.COMPLETE, dispatchEvent);
}

问题是我需要从监听器访问这个“index”变量,但我无法设置它作为全局变量,因为每个文件都有自己的索引,如果我必须扩展每个事件类来跟踪索引(事件、进度事件等),这将是一个负担。我希望有人能在这方面帮助我。

EDIT2:

我实际上找到了一个临时解决方案,我不确定它是否是最好的!我实际上将removeListener 方法放在upload 方法中,但将其设为变量。由于 AS3 允许动态对象,因此我将此方法附加到我的一个对象,因此我只需在必要时调用对该方法的引用。该事件实际上已被删除。请问这是一个好的解决方案吗?

非常感谢, 鲁迪

I have a strange issue! I am trying to remove an event listener on a FileReference object by calling a function, but it seems not to be removed, and I do not understand why.

Here is the code:

private function clearFileUploadListeners(file:FileReference, index:String):void {
    var dispatchEvent:Function = function(event:Event):void {
        dispatch(event.type, event, index);
    };

    file.removeEventListener(Event.COMPLETE, dispatchEvent);
    var bool:Boolean = file.hasEventListener(Event.COMPLETE);
    if (bool)
        trace("ERROR");
}

When I run this code, the trace actually happens. I don't understand why this boolean returns true, when I just tried to remove the eventListener just above! I guess I am probably doing something really stupid because it seems like a strange error.

I hope someone can please help me on this issue.

EDIT:

I believe it has to do with the fact that the dispatchEvent function is defined inside another function when I add the listener:

private function upload(file:FileReference, index:String):void {
    var dispatchEvent:Function = function(event:Event):void {
        dispatch(event.type, event, index);
    };

    file.addEventListener(Event.COMPLETE, dispatchEvent);
}

The problem is that I need to access this "index" variable from the listener, and I can't set it as a global variable as each file has it's own index and it's a burden if I have to extend each event class to keep track of the index (Event, ProgressEvent, ..). I hope someone can please help me on this.

EDIT2:

I actually found a temporary solution, I am not sure if it is the best! I put my removeListener method actually inside the upload method, but made it a variable. As AS3 allows dynamic object, I attached this method to one of my object, and so I just call the reference to the method when necessary. The event is actually removed. Is this a good solution please?

Thank you very much,
Rudy

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

变身佩奇 2024-09-13 06:41:01

你是对的,这与你在另一个函数中定义一个函数,然后使用它来处理事件有关。

每次调用函数upload时,它都会创建一个新的闭包< /a>,并将对其的引用分配给 dispatchEvent 变量,然后将该变量传递给 addEventListener 类。因此,每次调用 upload 时,它都会在调用 addEventListener 时使用新的、不同闭包。类似地,在 clearFileUploadListeners 函数中,每次调用都会创建一个新的闭包(每次都恰好具有相同的代码,但不是相同的函数对象)。如果给定回调尚未添加为给定事件的事件侦听器,则对 removeEventListener 的调用不会执行任何操作(此处就是这种情况)。

要解决您的问题,您需要存储对传递给 addEventListener 函数的闭包的引用。这样,当您稍后需要在 clearFileUploadListeners 中删除它时,您可以获得对添加的同一闭包的引用。

您可以尝试以下代码(未经测试):

import flash.utils.Dictionary;

var callbackRegistry:* = new Dictionary();


private function upload(file:FileReference, index:String):void {
    var dispatchEvent:Function = generateFileUploadCompleteCallback();

    callbackRegistry[file] = dispatchEvent;

    file.addEventListener(Event.COMPLETE, dispatchEvent);
}

private function clearFileUploadListeners(file:FileReference, index:String):void {
    var dispatchEvent:Function = callbackRegistry[file];
    callbackRegistry[file] = null;

    file.removeEventListener(Event.COMPLETE, dispatchEvent);

    var bool:Boolean = file.hasEventListener(Event.COMPLETE);
    if (bool)
        trace("ERROR");
    else
        trace("YAY, ALL OK!");
}

private function generateFileUploadCompleteCallback(index:String):Function {
    return function(event:Event):void {
        dispatch(event.type, event, index);
    };
}

You're right, it has to do with the fact that you're defining a function inside another function, then using it to handle events.

Each time the function upload is called, it creates a new closure, and assigns a reference to it to the dispatchEvent variable, which is then passed to the addEventListener class. So each time upload is called, it is using a new, different closure in the call to addEventListener. Similarly, in the clearFileUploadListeners function, a new closure is being created on each call (which happens to have the same code each time, but isn't the same function object). The call to removeEventListener does nothing if the given callback has not been added as an event listener for the given event, which is the case here.

To solve your problem, you need to store a reference to the closure that you pass to the addEventListener function. This way, you can get a reference to the same closure that was added when you need to remove it later in clearFileUploadListeners.

You can try something along the lines of the following code (untested):

import flash.utils.Dictionary;

var callbackRegistry:* = new Dictionary();


private function upload(file:FileReference, index:String):void {
    var dispatchEvent:Function = generateFileUploadCompleteCallback();

    callbackRegistry[file] = dispatchEvent;

    file.addEventListener(Event.COMPLETE, dispatchEvent);
}

private function clearFileUploadListeners(file:FileReference, index:String):void {
    var dispatchEvent:Function = callbackRegistry[file];
    callbackRegistry[file] = null;

    file.removeEventListener(Event.COMPLETE, dispatchEvent);

    var bool:Boolean = file.hasEventListener(Event.COMPLETE);
    if (bool)
        trace("ERROR");
    else
        trace("YAY, ALL OK!");
}

private function generateFileUploadCompleteCallback(index:String):Function {
    return function(event:Event):void {
        dispatch(event.type, event, index);
    };
}
耶耶耶 2024-09-13 06:41:01

关于这个主题还有两件事需要注意。

如果您必须直接使用原生事件,那么您应该始终确保并使用最后三个可选参数:

myObject.addEventListener( Event.COMPLETE, myFunction, false, 0, true );

在此处查看 Grant Skinner 关于该主题的帖子:
http://gskinner.com/blog/archives/2006/07/as3_weakly_refe.html

最好的做法是始终(认真地始终)使用 Robert Penner 的 Signals(而不是自定义事件)和他的 NativeSignals(包装所需的原生 Flash 事件)。

比 Flash 的本机事件快五倍。
弱引用总是安全的。
每个信号中任意数量的键入有效负载。

在这里获取 SWC:
https://github.com/robertpenner/as3-signals

信号旨在解决这个问题你正在拥有。
想象一下,如果您可以调用 : ,而不是创建一个数组并管理它来删除所有侦听器,

signalBtnClicked.removeAll();

或者

signalBtnClicked.addOnce( function( e : MouseEvent ) : void { /* do stuff */ } );

知道您刚刚创建的闭包在被调用后将立即被取消引用,并且当 GC 进行循环时,您会愉快地度过夜晚。

Two other things to note on this subject.

If you must utilize a native Event directly then you should pretty much always make sure and use these last three optional params :

myObject.addEventListener( Event.COMPLETE, myFunction, false, 0, true );

Check Grant Skinner's post on the subject here :
http://gskinner.com/blog/archives/2006/07/as3_weakly_refe.html

And the very best practice of all is to ALWAYS (seriously always) use Robert Penner's Signals (instead of custom events) and his NativeSignals (to wrap needed native Flash events).

Five times faster than Flash's native events.
Always safe with weak references.
Any number of typed payload(s) in each Signal.

Get the SWC here :
https://github.com/robertpenner/as3-signals

Signals were designed to solve the very problem you are having.
Imagine instead of creating an array and managing that to remove all listeners if you could just call :

signalBtnClicked.removeAll();

or

signalBtnClicked.addOnce( function( e : MouseEvent ) : void { /* do stuff */ } );

Knowing that the closure you just created will immediately be dereferenced once it is called and happily go night night when the GC makes its rounds.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文