0

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

下面是代码:

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"); 
} 

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

我希望有人能够帮助我解决这个问题。

编辑:

我相信这与该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”变量,并且我无法将其设置为全局变量,因为每个文件都有自己的索引,并且如果必须扩展每个事件类以跟踪索引(Event,ProgressEvent,。 )。我希望有人能够帮助我。

EDIT2:

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

非常感谢你, 鲁迪

回答

1

你说得对,它与您所定义功能的另一功能里面,然后用它来处理事件的事实做。

每当函数upload被调用时,它创建一个新closure,并分配参考它的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); 
    }; 
} 
+0

非常感谢,超清晰的解释,我明白了。我喜欢你的解决方案,它非常接近我的想法(我在上传函数中定义了一个removeListeners()函数,并将其存储到一个对象中)。 IE:object.var = removeListeners;那么object.var();它与你的相似,我不必费心跟踪字典,而是使用堆栈。谢谢你的帮助! – Rudy 2010-06-17 16:21:43

+0

很高兴有帮助:-) – Cameron 2010-06-18 01:11:35

0

两个其他的事情对这个问题注意。

如果必须利用本地事件直接,那么你应该非常总是确保并利用这最后的三个可选PARAMS:

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

检查格兰特斯金纳的职位上这里的主题: 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进行巡回演出时,快乐地过夜。