2011-01-06 3 views
2

Ich entwickle eine Flash-Anwendung, die Informationen von einem Remote-Server mit einem URLLoader erhält. Ich habe eine Funktion, die eine Anfrage nach Informationen basierend auf der Produkt-ID erstellen wird. Wenn ein Fehler auftritt, möchte ich auf eine alternative URL zurückgreifen, aber um die alternative URL zu erstellen, muss ich die Produkt-ID kennen. Was ist die beste Methode, um festzustellen, welcher URLLoader fehlgeschlagen ist (und welche Produktanfrage fehlgeschlagen ist), damit ich die neue URL neu generieren kann?Wie kann ich ermitteln, welcher URLLoader programmatisch fehlgeschlagen ist?

Meine Funktionen sind unter:

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); 
} 

Antwort

4

Sie Ihre Fehlerbehandlung in einer lokalen Variablen Wrap-könnte (was eine neue Funktion beschreibt), so können Sie die ID an die Methode übergeben, die das Fehlerereignis empfängt:

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); 
} 
+0

Ausgewählt, weil es wirklich einfach ist und die Frage elegant und mit minimalen Mengen an Code beantwortet. Wenn ich diese lange Zeit verwenden müsste oder wenn ich sie an mehr als einem Ort verwenden würde (wie bei anderen Projekten), würde ich wahrscheinlich die Lösung von Juan verwenden. – Steropes

+0

@Steropes, froh, dass es geklappt hat. Ich stimme dem zu - Juans Lösung ist sehr elegant und versteckt die Failover-Funktionalität. – bedwyr

7

mich korrigieren, wenn ich falsch bin, aber nicht e.target oder e.currentTarget die URLLoader, die gescheitert sind?

+0

+1 für sehr richtig sein. – weltraumpirat

+0

Ja. In Ihrer handleDataError-Funktion wird "e.currentTarget" für die Loader-Instanz ausgewertet. Von dort ist eine Option, die Sie haben, einfach auf die URL zuzugreifen, die Sie verwendet haben, und die ID zurückentwickeln? – Myk

+0

Ja, das e.target und e.currentTarget ruft den URLLoader ab, der fehlgeschlagen ist, aber es hat kein URL-Attribut, das mir Informationen darüber liefert, welcher URLLoader es ist. Ich suche nach der besten Möglichkeit, dieses URLLoader-Objekt mit anderen Daten, nämlich einer ProductID, zu verknüpfen. Mit anderen Worten: Wie verknüpfe ich das URLLoader-Objekt mit der Produkt-ID, um die Produkt-ID von einem unbenannten URLLoader-Objekt abzurufen? – Steropes

2

Eine Alternative zum Wrapper des Error-Handlers in eine Closure oder zum Abrufen der ID vom Ziel wäre das Schreiben eines benutzerdefinierten Loaders, der den Wiederholungsmechanismus verbirgt, sodass Sie ihn ähnlich wie einen normalen Loader verwenden könnten.

So etwas (ich dies nur im Notizblock schrieb, so hat es wahrscheinlich Fehler, aber nur Sie auf die Idee zu geben, ...):

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); 
     } 
    } 

} 

Dann in Ihrer Ladefunktion:

function loadData(productID:String):URLLoader { 

    var productLoader:ProductDataLoader = new ProductDataLoader(productId); 
    dataLoader.addEventListener(Event.COMPLETE, parseData); 
    dataLoader.addEventListener(IOErrorEvent.IO_ERROR, handleDataError); 
    dataLoader.load(); 
} 
+0

+1: Ich mag das besser als die Schließung Idee :) – bedwyr

+0

@bedwyr. Vielen Dank. Was ich an diesem Ansatz mag, ist, dass es den Mechanismus vor dem Aufrufer versteckt, so dass der aufrufende Code einfach bleibt. Wenn Sie eine robustere Fehlerbehandlung hinzufügen möchten (z. B. sicherstellen, dass der Loader in einem konsistenten Zustand bleibt, wird er beim Laden nicht erneut eingegeben), können Sie dies problemlos tun, ohne den "Client" -Code zu überladen kann diesen Lader fast wie einen normalen Lader behandeln. –

+0

Obwohl diese Lösung komplexer als der Code von Bedwyr ist, ist sie robuster und würde es mir ermöglichen, meine Anwendung zukunftssicher zu machen und es mir auf einfache Weise zu ermöglichen, den Code bei Bedarf wiederzuverwenden. Ich wählte Bedwyrs Lösung nur deshalb, weil ich eine einfache Lösung brauchte, die nur einmal verwendet wurde, und ich wählte die Codelesbarkeit über Robustheit. – Steropes

Verwandte Themen