2009-03-27 5 views
0

J'ai une étrange bizarrerie en ActionScript. Je dois passer l'index à une fonction de rappel.Émission d'événements étranges dans ActionScript3

Voici mon code

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'); 
} 

Toute idée sur la façon de passer l'indice à mes callbacks? ne bloque pas.

Répondre

2

Le passage de paramètres supplémentaires pour vos rappels est possible via une sorte de fonction déléguée ou de fermeture. Cependant, il est souvent considéré comme une mauvaise pratique. Vous pouvez utiliser la propriété d'événement target à la place pour déterminer votre index basé sur FileReference.

Edit: ici est un exemple d'utilisation des fermetures:

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(); 
} 

Cela tracera continuellement des chiffres de 0 à 9.

Edit2: ici est un échantillon de la création d'un délégué basé sur une fermeture de fonction:

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(); 

Toutefois, c'est un mauvais péché d'approche Ce désabonnement pour un tel auditeur est une douleur d'enfer. Cela entraînera probablement des fuites de mémoire, ce qui diminuera les performances globales de votre application. Donc, utilisez avec prudence!


Bottom line: si vous savez comment travailler avec les fermetures, les utiliser - il est une chose merveilleuse! Si vous ne vous souciez pas de la performance de votre application dans une perspective à long terme, utilisez des fermetures - c'est simple! Mais si vous n'êtes pas sûr des fermetures, utilisez une approche plus conventionnelle. Par exemple. dans votre cas, vous pouvez créer un Dictionary qui correspond à vos objets FileReference aux indices appropriés. Quelque chose comme ça:

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. 
    } 
} 

- Bonne codage!

+0

La 'target' ne fonctionnera pas pour moi parce que' target' ne me donnera que le 'FileReference', ce qui n'est pas ce dont j'ai besoin. –

+0

Mais 'FileReference's pour différents' lid's sont également différents. Au moins, vous pouvez les stocker dans un tableau et en trouver un nécessaire dans le rappel. – dragonfly

+0

Je peux également afficher l'exemple de délégué ou de fermeture. Mais c'est une mauvaise idée d'en utiliser un. – dragonfly

0

J'ai une bizarrerie étrange dans ActionScript

Ce n'est pas une bizarrerie, il est portée variable. Vous devriez lire cet article: http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f9d.html#WS5b3ccc516d4fbf351e63e3d118a9b90204-7f8c

Et vous ne devriez vraiment pas utiliser anonyme, cela rend tout plus confus. Vous êtes en train de faire plusieurs copies du même objet.

Si le arrayQueue est portée, vous pouvez utiliser ce code pour obtenir l'index:

GetArrayIndex(e.currentTarget); 

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

Vous devriez envisager d'utiliser un uint pour l'indice.

Questions connexes