ActionScript 3中的奇怪事件侦听

时间:2009-03-27 15:11:30

标签: javascript actionscript-3 events

我在ActionScript中有一个奇怪的怪癖。我需要将索引传递给回调函数。

这是我的代码

for (var i:Number = 0; ((i < arrayQueue.length) && uploading); i++)
{
    var lid:ListItemData=ListItemData(arrayQueue[i]);
    var localI:Number= new Number(i); // to copy?
    var errorCallback:Function = function():void { OnUploadError(localI); };
    var progressCallback:Function = function(e:ProgressEvent):void { lid.progress = e; OnUploadProgress(localI); };
    var completeCallback:Function = function():void { Alert.show('callback'+localI.toString()); OnUploadComplete(localI); }; // localI == arrayQueue.length - 1 (when called)
    Alert.show(localI.toString());  // shows current i as expected
    lid.fileRef.addEventListener(Event.COMPLETE, completeCallback);
    lid.fileRef.addEventListener(ProgressEvent.PROGRESS, progressCallback);
    lid.fileRef.addEventListener(HTTPStatusEvent.HTTP_STATUS, errorCallback);
    lid.fileRef.addEventListener(IOErrorEvent.IO_ERROR, errorCallback);
    lid.fileRef.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorCallback);

    lid.fileRef.upload(url, 'File');
}

关于如何将索引传递给我的回调的任何想法? .upload不会阻止。

2 个答案:

答案 0 :(得分:2)

通过某种委托函数或闭包可以传递回调的附加参数。然而,这通常被认为是一种不好的做法。您可以使用事件target属性来确定基于FileReference的索引。

编辑:以下是使用闭包的示例:

function getTimerClosure(ind : int) : Function {
    return function(event : TimerEvent) {
        trace(ind);
    };
}

for (var i = 0; i < 10; i++) {
    var tm : Timer = new Timer(100*i+1, 1);
    tm.addEventListener(TimerEvent.TIMER, getTimerClosure(i));
    tm.start();
}

这将连续跟踪0到9之间的数字。

Edit2:以下是基于函数闭包创建委托的示例:

function timerHandler(event : Event, ...rest) : void {
    trace(event, rest);
}

function Delegate(scope : Object, func : Function, ...rest) : Function {
    return function(...args) : void {
        func.apply(scope, args.concat(rest));
    }
}

var tm : Timer = new Timer(1000, 1);
tm.addEventListener(TimerEvent.TIMER, Delegate(this, this.timerHandler, 1, 2, 3));
tm.start();

然而,这是一个糟糕的方法,因为取消订阅这样的听众是一种地狱般的痛苦。这反过来可能会导致一些内存泄漏,这将降低应用程序的整体性能。 所以,请谨慎使用!


底线:如果您知道如何使用闭包,请使用它们 - 这是一件很棒的事情!如果您从长远角度不关心应用程序性能,请使用闭包 - 这很简单!

但如果您不确定关闭,请使用更传统的方法。例如。在您的情况下,您可以创建一个Dictionary,将FileReference个对象与适当的索引相匹配。这样的事情:

var frToInd : Dictionary = new Dictionary(false);
// false here wouldn't prevent garbage collection of FileReference objects

for (var i : int = 0; i < 10; i++) {
    // blah-blah stuff with `lib` objects
    frToInd[lib.fileRef] = i;
    // another weird stuff and subscription 
}

function eventListener(event : Event) : void {
    // in the event listener just look up target in the dictionary
    if (frToInd[event.target]) {
        var ind : int = frToInd[event.target];
    } else {
        // Shouldn't happen since all FileReferences should be in 
        // the Dictionary. But if this happens - it's an error.
    }
}

- 快乐的编码!

答案 1 :(得分:0)

  

我在ActionScript中有一个奇怪的怪癖

这不是一个怪癖,它的范围可变。您应该阅读这篇文章:http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f9d.html#WS5b3ccc516d4fbf351e63e3d118a9b90204-7f8c

你真的不应该使用匿名,这只会使一切更加混乱。你实际上正在制作同一个对象的多个副本。

如果 arrayQueue 在范围内,您可以使用此代码获取索引:

GetArrayIndex(e.currentTarget);

function GetArrayIndex(object:Object):Number
{
    for(var i:Number = 0; 0 < arrayQueue.length; i++)
    {
        if(object === arrayQueue[i])
            return i;
    }
}

您应该考虑使用uint作为索引。