views:

710

answers:

3

Basically I've got a code which should load a lot of images so I need a function to load them. The problem is that addEventListener requires a function which it will call when the event have been raised.

I need to find a way to either make the loadImage function return ONLY after the event was raised or make the function raised in addEventListener to return it's parent function.

 function loadImage(imagePath:String)//:BitmapData
 {
   var internalLoader:Loader = new Loader();

   var internalImageRequest = new URLRequest(imagePath); 

   var loadingComplete:Boolean = false;

   internalLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, 
                 function (event:Event):void
                 {
                loadingComplete = true;
                 }
                 );
   internalLoader.load(internalImageRequest);



   //I need to wait 'till the event have been raised and then RETURN , NOT BEFORE THAT
   //var tempImg:Bitmap = Bitmap(internalLoader.content);
   //return tempImg.bitmapData;
 }

Thanks in advance

+2  A: 

Short answer: Give it up, it's not going to happen that way.

Long answer: The thing here is that you never want to Flash Player to hang. Reasons for that are many but all boils down to the fact that you're always operating in the UI thread. A network request such as yours would mean you have to wait for the image to load which would hang the UI while waiting and thus annoying the user. If the image is small and network efficiency is not an issue then this is not a problem for you. However, if the image takes a while to load the problem rears it's head. Also, the Flash Player puts a limit on code execution time per frame, 15 seconds if I recall correctly. After that, the user gets a popup asking if the script should be aborted.

What I suggest that you do instead is define an event handler which does whatever it is you need to do with the BitmapData object that you get from the loader.

function loadImage(imagePath:String):void
{
    var internalLoader:Loader = new Loader();
    var internalImageRequest = new URLRequest(imagePath); 

    var loadingComplete:Boolean = false;

    internalLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoad);
    internalLoader.load(internalImageRequest);
}

function onLoad(event:Event):void
{
    // Do whatever you need to do with the loader here
    var contentLoaderInfo:LoaderInfo = LoaderInfo(event.target);
}
macke
A: 

Unfortunately, that's not possible. You need an event that your parent function registers. Then when the loader finishes loading, it raises the event. You can pass your bitmap data in eventargs.

ie

function (event:Event):void 
{
    loadingComplete = true;
    dispatchEvent([Your Event]);
}

Your parent needs to listen to [Your Event] and does whatever it needs.

David
A: 

You could also try Continuation Passing Style:

function loadImage(path:String, result:Function):void {
    var l:Loader = new Loader();
    l.load(new URLRequest(path));
    l.contentLoaderInfo.addEventListener(Event.COMPLETE, function(event:Event):void {
        result(Bitmap(l.content).bitmapData);
    });
    // If you want to handle IO errors, otherwise this effectively never "returns".
    l.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, function(event:Event):void {
        result(null);
    });
}

function process(path:String):void {
    loadImage(path, function(data:BitmapData):void {
        ...
    }
}

This gets very painful when you have to chain multiple functions, so you can break standard formatting:

function process(path:String):void {
    loadImage(path, function(
    data:BitmapData):void { // Async "result declaration"

    longProcessing(data, function(
    result:ProcessingResult):void {

    // Can use data and result here...
}}} // Have to close continuations as well as process
Simon Buchan