我在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
不会阻止。
答案 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作为索引。