2011-12-28 50 views
2

所以,我希望在某些情況下收集某些條件滿足時要調用的函數。例如。在actionscript中收集和識別數組中的函數

function doSomething(someArg:Object):void { 
    if (conditionIsFalse){ 
     operationsToDoWhenConditionIsTrue.push(function(){ 
      doSomething(someArg); 
     }); 
    } 
} 

function onConditionBecomingTrue():void { 
    while (operationsToDoWhenConditionIsTrue.length > 0){ 
     operationsToDoWhenConditionIsTrue.shift()(); 
    }  
} 

到目前爲止好。然而,在某些時候,我想迭代operationsToDoWhenConditionIsTrue並識別並替換一個函數。在DoSomething的方法中的僞代碼將是:

function doSomething(someArg:Object):void { 
    if (conditionIsFalse){ 
     for (var i:int = 0; i<operationsToDoWhenConditionIsTrue; i++){ 
     // pseudo code here 
     if (typeof operationsToDoWhenConditionIsTrue[i] == doSomething){ 
      operationsToDoWhenConditionIsTrue[i] = doSomething(someArg); 
     } 
     } 
    } 
} 

基本上如果DoSomething的叫了兩次,我只想operationsToDoWhenConditionIsTrue保持最近的調用。顯然,由於調用被封裝在函數(){}中,所有函數都是相同的。有什麼方法可以完成我想要的嗎?

+0

標識相同操作的標準是什麼?操作是否用不同的'doSomething'功能標識(即每個之間有1-1映射)? – outis 2011-12-29 00:25:31

+0

是的,我現在意識到,如果你只是刪除typeof,那麼我的僞代碼就有點類似了。 – pondermatic 2011-12-29 18:56:54

回答

1

創建一個標識符功能,可以識別您想要檢測的操作。將該ID分配爲您添加到隊列中的匿名函數的屬性。在迭代隊列時,在集合中記錄ID。如果它已經在集合中,請不要執行該操作。

function doSomething(someArg:Object):void { 
    if (conditionIsFalse){ 
     var operation = function(){ 
      doSomething(someArg); 
     }; 
     operation.operationID = objID(...); 
     operationsToDoWhenConditionIsTrue.push(operation); 
    } 
} 

function onConditionBecomingTrue():void { 
    var done = {}, f; 
    while (operationsToDoWhenConditionIsTrue.length > 0){ 
     f = operationsToDoWhenConditionIsTrue.shift(); 
     if (! f.operationID in done) { 
      done[f.operationID] = true; 
      f() 
     } 
    }  
} 

作爲這種更有效的變體,您可以通過ID爲隊列建立索引,以便函數只能添加一次到隊列中。但是,您將失去對操作執行順序的控制。

var operationsToDoWhenConditionIsTrue:Object = {}; 

function doSomething(someArg:Object):void { 
    if (conditionIsFalse){ 
     operation.operationID = ...; 
     operationsToDoWhenConditionIsTrue[objID(...)] = function(){ 
      doSomething(someArg); 
     }; 
    } 
} 

function onConditionBecomingTrue():void { 
    for (id in operationsToDoWhenConditionIsTrue){ 
     operationsToDoWhenConditionIsTrue[id](); 
    } 
    operationsToDoWhenConditionIsTrue = {}; 
} 

如果您需要保存的順序(這樣操作是爲了執行他們首先被添加到隊列,或在他們最後添加的順序),創建可由雙方進行索引隊列類型ID和序列,你可以通過存儲索引類型之間的映射來完成。注意:以下是未經測試的。

class OperationQueue { 
    protected var queue:Array = []; 
    protected var idToSeq:Object = {}; 

    public function push(op:Function):void { 
     /* Orders by last insertion. To order by first insertion, 
      simply return if the operation is already in the queue. 
     */ 
     if (op.id in this.idToSeq) { 
      var seq = this.idToSeq[op.id]; 
      delete this.queue[seq]; 
     } 
     this.queue.push(op); 
     this.idToSeq[op.id] = this.queue.length-1; 
    } 
    public function runAll():void { 
     var op; 
     while (this.queue.length > 0) { 
      if ((op = this.queue.shift())) { 
       delete this.idToSeq[op.id]; 
       op(); 
      } 
     } 
    } 
} 
+0

感謝這一變化做到了。我結束了使用一個數組作爲索引和參數作爲值。然後,當它調用時,我使用func.apply(this,args)。這消除了操作ID的需要。 – pondermatic 2011-12-29 19:00:22

+0

請注意,對象屬性必須是整數或字符串;使用函數意味着它首先轉換爲一個字符串。這應該仍然有效,因爲兩個不同的函數不太可能具有相同的形式參數和正文。另一種方法是使用[Dictionary](http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/utils/Dictionary.html),它可以將對象作爲關鍵字。 – outis 2011-12-29 19:29:24