1

Why isn't this working as I am thinking it would:

var i:int=-1;
for each(obj in myData)
{
    i++;
    var loader:Loader=new Loader();
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE,function(event:Event)
    {
        trace(i);
    });
}

There are 3 objects in myData and the trace statement looks like:

2
2
2

Instead of:

0
1
2

If I add i to an array (like myArr.push(i)) it will have 3 elements, 0, 1 and 2.

Any ideas? Thank you.

Francisc
  • 77,430
  • 63
  • 180
  • 276

2 Answers2

3

That's a very bad approach you've taken... Just don't do any of those things you are trying to do, and it'll be fine... No point in using anonymous function here (it's never actually in AS3), no point to use for-each, because what you need is for(;;). You use dynamic typing for no benefit what so ever (there's no benefit in dynamic typing in AS3 and never was anyway). And, yeah, the closure will capture the context, the context has only one i, and it's value is 2, so the first trace is what you should expect.

What you should be doing - store the loaders in some data structure and fetch them from that data structure later (when you need that identifier). And please, for the sake of us users, load whatever you are trying to load sequentially - because if you don't, we'll get the IO errors you aren't handling...

  • I think it's an over-generalization that you don't ever need anonymous functions in AS3. However, if you're having trouble with the concepts you need to understand functional programming, you probably should avoid them. For more information on how to do functional programming properly, check out http://www.developria.com/2010/12/functional-actionscript-part-1.html – Amy Blankenship Oct 22 '11 at 15:39
  • Used with care and understanding, anonymous functions are no worse than any other language feature. Used without care and understanding, they can be as disasterous as other features people don't generally recognize as dangerous, such as statics (but that can be way worse in their way ) – Amy Blankenship Oct 23 '11 at 02:13
  • Thank you. The code above is a simplified example to show the problem. It's not the actual code. I am listening for IOErrors, I am not declaring var loader:Loader each time and so on. That thing above works in JS and was having trouble understanding why it is not working here. – Francisc Oct 23 '11 at 10:12
  • Why should I not use for each? – Francisc Oct 23 '11 at 10:16
1

First let me tell you why it doesn't work as you expect. What is happening is, the for is looping through your elements, and creates all the loaders, incrementing i, but the Event.COMPLETE happens sometime later, where the i is already at the value 2, so that's why you get that output.

As wvxvw suggested, you need some more data structure, something like this:

class MyLoader {

    private var i: int;
    private var loader: Loader;

    function MyLoader(i:int) {
        this.i = i;

        loader = new Loader();
        loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
    }

    function onLoaded(event:Event)
    {
        trace(i);
    }
}

And you will use it in your loop:

var i:int = 0;
for each(obj in myData) {
    var loader:MyLoader=new MyLoader(i++);    
}

Of course, you will need to add lots more to that MyLoader, like handling the errors, and pass more meaningful things to make everything work.

Cristi Mihai
  • 2,505
  • 1
  • 19
  • 20
  • Ah, I understand now. The anonymous function fires when all bytes are loaded. I was thinking it keeps is as a "variable" like JS does and holds in it as was when it was declared. Thanks. – Francisc Oct 23 '11 at 10:15
  • 1
    You're thinking about the closures in JavaScript.. ActionScript (being ECMAScript variant) does that too, but you'll have to wrap everything in another function and store `i` in a local variable, like this: http://pastebin.com/iRdMZ0uc. – Cristi Mihai Oct 23 '11 at 11:26