所以,我想做一些事情,我收集函数,以便在满足某个条件时调用。 E.g。
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来保存最近的调用。显然,由于调用包含在function(){}中,因此所有函数都是相同的。有什么方法可以实现我的目标吗?
答案 0 :(得分: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();
}
}
}
}