Странное прослушивание событий в ActionScript3 - PullRequest
0 голосов
/ 27 марта 2009

У меня есть странная причуда в 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 ]

2 голосов
/ 27 марта 2009

Передача дополнительных параметров для ваших обратных вызовов возможна с помощью некоторой функции делегата или замыкания. Однако это часто считается плохой практикой. Вместо этого вы можете использовать свойство события 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.
    }
}

- Удачного кодирования!

0 голосов
/ 27 марта 2009

У меня есть странная причуда в 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 для индекса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...