gpt4 book ai didi

flash - 如何在 Actionscript 3 中对事件进行排序

转载 作者:行者123 更新时间:2023-12-01 12:00:30 25 4
gpt4 key购买 nike

在过去的几周里,我一直在使用 AS3,但遇到了 Google 无法解决的问题。问题的症结在于,在我运行函数之前,我需要知道某些条件已经满足,例如加载我的 config.xml 并将其放入类变量中。我遇到麻烦的地方是 URLLoader 是异步的,所以我不能在加载后放置代码,我唯一能做的就是把它放在监听器的 lambda 中。

var conf:Object = new Object();

var ldr:URLLoader = new URLLoader();
ldr.addEventListener(Event.COMPLETE, geoLoader, false, 0, true);
ldr.load(new URLRequest("http://ipinfodb.com/ip_query.php"));

function geoLoader (e:Event):void
{
var data = new XML(e.target.data);

conf.zip = data.ZipPostalCode.toString();
conf.city = data.City.toString();
conf.state = data.RegionName.toString();
}

或者更简洁一点,我相信更容易理解:

var conf:Object = new Object();

var ldr:URLLoader = new URLLoader();
ldr.addEventListener(Event.COMPLETE, function (e:Event){
var data = new XML(e.target.data);

conf.zip = data.ZipPostalCode.toString();
conf.city = data.City.toString();
conf.state = data.RegionName.toString();
}, false, 0, true);
ldr.load(new URLRequest("http://ipinfodb.com/ip_query.php"));

这对于短代码非常有效,但我有一堆依赖大量先决条件的函数(如果我使用第一种方法,这会污染命名空间)或依赖其中一部分的函数堆栈(这意味着我不能使用第二种方法,尽管它对我来说稍微明显一些)。

那么,我的问题是:Flash 专业人员如何处理先决条件?我正在尝试找到一个允许大量先决条件的解决方案,以及一个允许不同顺序的先决条件或仅允许一组先决条件的解决方案。

编辑:我不确定我最初是否说清楚了,但问题是我将有 5 个先决条件,这意味着我最终得到上述 block 中的 5 个。正如您可以想象的那样,有 5 个嵌套的监听器会产生糟糕的意大利面条代码。举个例子,我的一个函数需要知道:何时加载 config.xml,何时更新位置,何时加载当前天气状况,以及何时加载当前天气的图像。但是,还有另一个函数只需要知道何时加载 config.xml 和更新位置。所以这是一组非常复杂的事件,但我确信我不是唯一一个必须处理一组复杂事件的人。

同样值得注意的是,我查看了 Senocular 的 Sequence.as,但据我所知,它是基于返回而非事件的。但我可能错了。

感谢您提供的任何帮助!

最佳答案

我结合使用开源库和自定义类来处理这种情况。

对于加载,我主要使用 BulkLoader因为它将处理您想要加载的任何内容,并准备好监听所有事件。

我努力做的主要事情是尽可能让我的实现解耦。出于这个原因,任何依赖数据的功能都是通过订阅、通知设置来处理的。我使用一个自定义类,我称之为 DataController。 DataController 是一个单例类,具有一些核心功能,包括:

订阅,通知

假设我有这样的情况,我想加载一堆图像,但只有当包含图像路径的 XML 已完全加载时我会这样做:

在我的文档类或其他一些 Controller 类型类中,我会使用 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]);
}
}

基本上,当您调用 subscribe 时,它​​会首先检查 $eventName 数据是否已在 _processed 中设置。如果有,它将将该数据传递给它的订阅函数(在本例中为 _populate。)如果尚未加载,它将把订阅函数添加到 _subscribers 字典并且什么都不做。当通过通知发送数据时,它会首先在 _processed 字典中设置,然后 DataController 将循环并为 $eventName 订阅者并将数据传递给每个订阅函数。

还有一些方法我省略了,它们可以让你做同样的事情,但实际上没有传递任何数据。这些对于动画事件或将任何其他类型的事件链接在一起很有用。

我还有删除订阅者和从 _processed Dictionary 中删除数据的方法。

我希望这一切都有意义。

编辑

根据您的编辑,您可以执行以下操作:

在某处编码,也许在您的文档类中。

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

在某处编码,也许是一些天气显示 View :

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。之后它会加载其他东西……等等。

您还可以使用 BulkLoader 加载您的 5 个东西,并监听每个东西是否完成。根据需要触发通知和广播。

关于flash - 如何在 Actionscript 3 中对事件进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2238498/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com