2009-03-27 6 views
0

私はActionScriptで気まぐれな癖があります。インデックスをコールバック関数に渡す必要があります。ここでActionScript3で奇妙なイベントリスニング

は私のコード

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

コールバックの追加パラメータを渡すことは、何らかの種類のデリゲート関数またはクロージャを介して可能です。しかし、それはしばしば悪い習慣とみなされます。代わりにイベント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(); 

しかし、これは悪いアプローチsinそのような聞き手のための購読を中止することは、地獄の痛みです。これはおそらくメモリーリークを引き起こし、アプリケーションの全体的なパフォーマンスを低下させます。 だから、慎重に使用してください!


ボトムライン:あなたは、クロージャと連携する方法を知っていれば、それらを使用する - それは素晴らしいことです!長い視点でアプリケーションのパフォーマンスを気にしない場合は、クロージャを使用してください。これは簡単です!

しかし、クロージャについてわからない場合は、従来の方法を使用してください。例えば。あなたの場合、FileReferenceオブジェクトを適切なインデックスに一致させるDictionaryを作成することができます。そのようなもの:

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

'target'は私に必要なものではない' FileReference'を取得するだけなので、 'target'は私のためには機能しません。 –

+0

しかし、異なる 'lid'sの' FileReference'も異なっています。少なくともそれらをArrayに格納し、コールバックに必要なものを見つけることができます。 – dragonfly

+0

また、デリゲートまたはクロージャのサンプルを表示することもできます。しかし、それを使うのは悪い考えです。 – dragonfly

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の使用を検討すべきです。