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進行巡迴演出時,快樂地過夜。