Я использую комбинацию библиотек с открытым исходным кодом и пользовательских классов для обработки именно этого типа ситуации.
Для загрузки я в основном использую BulkLoader , поскольку он будет обрабатывать все, что вы хотите загрузить, и все события готовы для прослушивания.
Главное, к чему я стремлюсь, - это максимально отделить мою реализацию. По этой причине любая функция, которая опирается на данные, обрабатывается посредством подписки, настройки уведомлений. Я использую пользовательский класс, который я называю DataController. DataController - это одноэлементный класс, который имеет несколько основных функций, включая:
subscribe, notify
Допустим, у меня есть ситуация, когда я хочу загрузить кучу изображений, но только тогда, когда мой XML, содержащий пути к изображениям, полностью загружен
Я бы сделал это так:
Внутри моего класса документов или какого-то другого класса типов контроллеров я бы использовал BulkLoader для загрузки некоторого XML. В полном обработчике я бы взял XML, скажем imageXML и выполнил команду, подобную этой:
DataController.instance.notify("ImageXMLLoaded", imageXML);
В моем классе ImageHolder у меня было бы следующее:
public function ImageHolder() {
DataController.instance.subscribe("ImageXMLLoaded", _populate);
}
private function _populate($imageXML:XML):void {
// do whaterver with your XML
}
DataController имеет несколько переменных экземпляра, подобных этим:
private var _subscribers:Dictionary = new Dictionary(true);
private var _processed:Dictionary = new Dictionary(true);
private var _requests:Dictionary = new Dictionary(true);
Функция подписки выглядит примерно так:
public function subscribe($eventName:String, $subscriber:Function): void {
var _funcArray:Array;
var _func:Function;
if (_processed[$eventName]) {
$subscriber(_processed[$eventName]);
return;
}
if (! _subscribers[$eventName]) {
_subscribers[$eventName] = new Array();
}
_subscribers[$eventName].push($subscriber);
}
И функция уведомления выглядит так:
public function notify($eventName:String, $data:*, $args:Object = null): void {
var _cnt:Number;
var _subscriberArray:Array;
var _func:Function;
_processed[$eventName] = $data;
if (_subscribers[$eventName] != undefined) {
_subscriberArray = _subscribers[$eventName].slice();
_cnt = 0;
while (_cnt < _subscriberArray.length) {
_func = _subscriberArray[_cnt] as Function;
if ($args) {
_func($feedXML, $args);
} else {
_func($feedXML);
}
_cnt++;
}
}
if (_requests[$eventName]) {
_subscriberArray = _requests[$eventName].slice();
delete _requests[$eventName];
_cnt = 0;
while (_cnt < _subscriberArray.length) {
if (_subscriberArray[_cnt] != null) {
_subscriberArray[_cnt]($data);
}
_cnt++;
}
}
}
И моя функция запроса:
public function request($eventName:String, $requestFunction:Function): void {
var _requestArray:Array;
var _request:Function;
if (! _feeds[$eventName]) {
if (! _requests[$eventName]) {
_requests[$eventName] = new Array();
}
_requests[$eventName].push($feedFunction);
} else {
$requestFunction(_feeds[$eventName]);
}
}
Обычно, когда вы вызываете подписку, он сначала проверяет, были ли уже установлены данные $ eventName в _processed. Если это так, он передает эти данные в свою функцию подписки (в данном случае _populate.) Если она не была загружена, он добавит функцию подписки в словарь _subscribeers и больше ничего не будет делать. Когда данные отправляются с помощью уведомления, они сначала устанавливаются в _processed Dictionary, затем DataController зацикливается и подписывается на $ eventName и передает данные каждой из функций подписки.
Есть также методы, которые я пропустил, которые позволяют вам делать то же самое, но без фактической передачи каких-либо данных. Они полезны для анимации событий или для сцепления любых других типов событий.
У меня также есть методы для удаления подписчиков и удаления данных из _processed Dictionary.
Надеюсь, все это имеет смысл.
EDIT
Исходя из ваших правок, вы можете сделать что-то вроде этого:
Код где-то, может быть, в вашем классе документов.
public function startMyLoading():void {
loadConfig(onConfigLoaded);
}
public function onConfigLoaded($xml:XML):void {
DataController.instance.notify("configLoaded", $xml);
loadWeatherContiditons(onWeatherConditionsLoaded);
}
public function onWeatherConditionsLoaded($xml:XML):void {
DataController.instance.notify("weatherXMLLoaded", $xml);
}
Код где-то, может быть, какой-то вид отображения погоды:
public function WeatherDisplayView():void {
DataController.instance.subscribe("weatherXMLLoaded", _populateWeatherPanel);
}
private function _populateWeatherPanel($xml:XML):void {
// for each (var weatherNode:XML in $xml.children()) ...
// use BulkLoader to load, and add Event.COMPLETE function for when it is finished.
}
private function _onBulkLoaderComplete($evt:Event):void {
DataController.instance.broadcast("ImagesComplete"); // the broadcast function is one that I did not include above, but basically works the same as subscribe, notify, but without any data being passed.
}
Код в чем-то, требующем загрузки только config.xml:
public function SomeClass():void {
DataController.instance.subscribe("configLoaded", _handleConfigLoaded);
}
private function _handleConfigLoaded($xml:XML):void {
// do something with config
}
При использовании этого метода ваши запросы фактически синхронны. После загрузки config.xml загружается weather.xml. После этого он загружает что-то еще ... и т. Д. И т. Д.
Вы также можете загрузить свои 5 вещей с помощью BulkLoader и прослушать каждую из них для завершения. Запуская уведомления и трансляции по мере необходимости.