Avg. Rating 3.0

Problem

Since file loading in the Flash/Flex/AS3 world is completely asynchronous, when you need to load more than one file, the hackish solution is to make the COMPLETE handler for the first one initiate the load for the second, etc. until all the files are loaded. This is obviously less than ideal.

Solution

This URLMultiLoader class will load multiple files and optionally "process" them before calling the method you specify for Event.COMPLETE.

Detailed explanation

The URLMultiLoader class discussed in this post will load multiple files and optionally "process" them before calling the method specified for Event.COMPLETE.

Since file loading in the Flash/Flex/AS3 world is completely asynchronous, when you need to load more than one file, the hackish solution is to make the COMPLETE handler for the first one initiate the load for the second, etc. until all the files are loaded. URLMultiLoader will allow you to setup one COMPLETE handler which will not be called until all the files you specify are loaded (and optionally "processed").

When I first had need for this, I said to myself that someone must have done this before. It seems like a fairly common need. However, when I went looking, I couldn't find something that fit the bill, so I decided to write my own. It was actually a very good way to get familiar with the event system. Also, while I was at it, I figured I'd allow the injection of a processor for each file and make sure that got processed before proceeding. If anyone knows of another tool like this please post a link to it in the comments. Actually, it wouldn't surprise me if this functionality is built into the Flex framework somewhere and I just missed it.

In the source code package linked below, DataProcessorXMLStringToArray is provided as an example IDataProcessor that can optionally be passed in when adding a new URLRequest to the queue. If provided, an IDataProcessor will convert the raw file string (or binary, or url variables) into some other form before returning. Complete documentation for DataProcessorXMLStringToArray is provided in the ASDoc header for the class but it is offered primarily as an example. You can easily create your own and inject them when setting up the URLMultiLoader. You just need to follow the IDataProcessor interface which has one method with the following signature:

function processData(data:*):*

Remember, the processor is totally optional. If omitted, URLMultiLoader will simply copy the file contents into it's output data field. The type of the data in that case will depend upon the URLLoaderDataFormat: String for TEXT (default), ByteArray for BINARY, and URLVariables for VARIABLES.

Let's see it in action.

package {
	import com.maccherone.urlmultiloader.*;
	import com.maccherone.json.JSON;  // Only used for pretty output

	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.Dictionary;

	public class MultiFileLoaderTest extends Sprite
	{
		private var urlMultiLoader:URLMultiLoader = new URLMultiLoader()
		private var baseURL:String = "http://maccherone.com/publications/"
		private var urlRequest1:URLRequest = new URLRequest(baseURL + "file.xml")
		private var urlRequest2:URLRequest = new URLRequest(baseURL + "file.xml")  // Same file but we'll get it in a different format
		private var urlRequest3:URLRequest = new URLRequest(baseURL + "smile.gif")

		public function MultiFileLoaderTest() {
			var urlMultiLoader:URLMultiLoader = new URLMultiLoader

			var dataProcessor:IDataProcessor = new DataProcessorXMLStringToArray()  // Example provided with URLMultiLoader. You can create your own.

			urlMultiLoader.addURLRequest(urlRequest1, dataProcessor)
			urlMultiLoader.addURLRequest(urlRequest2)  // If no IDataProcessor is provided, then file's contents is returned as String, ByteArray, or
			                                           // URLVariables depending upon the URLLoaderDataFormat TEXT, BINARY, or VARIABLES respectively
			urlMultiLoader.addURLRequest(urlRequest3, null, URLLoaderDataFormat.BINARY)  // Loads smile.gif as a ByteArray

			urlMultiLoader.addEventListener(Event.COMPLETE, filesLoaded)
			urlMultiLoader.addEventListener(IOErrorEvent.IO_ERROR, onError)
			urlMultiLoader.load()
		}

		private function filesLoaded(event:Event):void {
			var urlInfoDictionary:Dictionary = (event.target as URLMultiLoader).urlInfoDictionary
			trace("Array of Objects:\n" + JSON.encode(urlInfoDictionary[urlRequest1].data, true) + "\n") // Uses JSON.encode for pretty output
			trace("String of file contents:\n" + urlInfoDictionary[urlRequest2].data + "\n")
			var loader:Loader = new Loader();
			loader.loadBytes(urlInfoDictionary[urlRequest3].data);
			this.addChild(loader)  // Displays smile.gif in Flash player
		}

		private function onError(event:Event):void {
			trace(event)
		}
	}
}

The above code would result in the following output:

Array of Objects:
[
    {"id": 101, "name": "/db/node/visitor"},
    {"id": 102, "name": "/db/node/observer"},
    {"id": 103, "name": "/ui/button"}
]

String of file contents:
<?xml version="1.0" encoding="UTF-8"?>
<root>
  <file>
    <id>101</id>
    <name>/db/node/visitor</name>
  </file>
  <file>
    <id>102</id>
    <name>/db/node/observer</name>
  </file>
  <file>
    <id>103</id>
    <name>/ui/button</name>
  </file>
</root>

Plus it will display smile.gif in the Flash player like this:

smile_in_flash_player

Note, the above sample code uses my JSON pretty printer (adapted from as3corelib's JSON encoder) to demonstrate URLMultiLoader's capability. You can easily remove the reference in the sample code or you can download it from here.

You can download URLMultiLoader in source or swc form from here.

Report abuse

Related recipes