How do I determine which URLLoader failed programmatically?
I'm developing a flash application that is getting information from a remote server using a URLLoader. I have a function that will create a request for information based on the product ID. When there is an error, I want to fall back to an alt开发者_JAVA技巧ernate URL, but to create the alternate URL, I need to know the product ID. What is the best method to determine which URLLoader failed (and which product request failed) so that I can regenerate the new URL?
My functions are below:
function loadData(productID:String):URLLoader {
var productURL:URLRequest = new URLRequest("/path/to/product/" + productID);
var dataLoader:URLLoader = new URLLoader();
dataLoader.addEventListener(Event.COMPLETE, parseData);
dataLoader.addEventListener(IOErrorEvent.IO_ERROR, handleDataError);
dataLoader.load(productURL);
return dataLoader;
}
function handleDataError(e:IOErrorEvent) {
var productID:String = ???;
var altProductURL:URLRequest = new URLRequest("/alternate/path/to/product/" + productID);
var dataLoader:URLLoader = new URLLoader();
dataLoader.load(altProductURL);
}
Correct me if I'm wrong, but won't e.target
or e.currentTarget
be the URLLoader that failed?
You could wrap your error handler in a local variable (which describes a new function) so you can pass the ID to the method which receives the error event:
function loadData(productID:String):URLLoader {
var productURL:URLRequest = new URLRequest("/path/to/product/" + productID);
var dataLoader:URLLoader = new URLLoader();
var errHandler:Function = function(event:IOErrorEvent):void {
handleDataError(event, productID);
};
dataLoader.addEventListener(Event.COMPLETE, parseData);
dataLoader.addEventListener(IOErrorEvent.IO_ERROR, errHandler);
dataLoader.load(productURL);
return dataLoader;
}
function handleDataError(e:IOErrorEvent, productID:String) {
var altProductURL:URLRequest = new URLRequest("/alternate/path/to/product/" + productID);
var dataLoader:URLLoader = new URLLoader();
dataLoader.load(altProductURL);
}
An alternative to wrapping the error handler in a closure or retrieving the id from the target would be writting a custom loader that hides the retry mechanism, so your could use it pretty much like if it were a normal loader.
Something like this (I just wrote this in notepad, so it probably has errors, but just to give you the idea...):
public class ProductDataLoader extends EventDispatcher {
private var _paths:Array;
private var _id:String;
private var _state:int;
private var _loader:URLLoader;
private var _data:Object;
public function get data():Object {
return _data;
}
public function ProductDataLoader(id:String) {
_paths = [
"/path/to/product/",
"/alternate/path/to/product/"
];
_id = id;
_state = -1;
_loader = new URLLoader();
_loader.addEventListener(Event.COMPLETE, handleComplete);
_loader.addEventListener(IOErrorEvent.IO_ERROR, handleError);
}
public function load():void {
if(hasNextPath()) {
_loader.load(new URLRequest(getNextPath()));
} else {
// here, we ran out of paths to try
// you shouldn't get here unless you call loadProduct()
// more than once.
// you should probably throw an error here, but that's up to
}
}
private function hasNextPath():Boolean {
return _state < _paths.length - 1;
}
private function getNextPath():String {
_state++;
return _paths[_state] + _id;
}
private function handleComplete(e:Event):void {
// redispatch the complete event
_data = _loader.data;
dispatchEvent(e);
}
private function handleError(e:Event):void {
if(hasNextPath()) {
loadProduct();
} else {
// we tried all paths without success
// so we just redispatch the error event
dispatchEvent(e);
}
}
}
Then in your load function:
function loadData(productID:String):URLLoader {
var productLoader:ProductDataLoader = new ProductDataLoader(productId);
dataLoader.addEventListener(Event.COMPLETE, parseData);
dataLoader.addEventListener(IOErrorEvent.IO_ERROR, handleDataError);
dataLoader.load();
}
精彩评论