假设我在AS3中有类似的代码
for(...)
thing = new Thing(...)
Thing的构造函数将导致swf渲染到某个movieclip上。 如果循环运行10次左右,大部分时间我只会在剪辑上显示一部分东西。我猜这是一个问题,闪存同时加载了一堆东西。
我已经能够通过将回调传递给Thing构造函数来解决这个问题,并且只有在前一个Thing完全加载并且回调后才继续循环。
首先,这是一个已知的问题吗?或者我是以错误的方式解决这个问题? 其次,有没有什么方法可以告诉flash /在没有回调的情况下以线性方式运行此代码?到处都是这样做很烦人。
编辑:
所以我认为richardolsson是对的,我们必须做错事。要重述这个问题,如果我尝试将多个swfs加载到舞台上,即使只有两个或三个,而不等待前一个完成加载,我将加载一个未预测的数字。例如,运行循环10次以上,我可能最终得到第2,第5和第10件事。其他人似乎在异步中迷失了方向。 Flash在这些情况下不显示运行时错误。所以这是我们如何做事的基本思路。
我们有一个基类,我们为大多数加载swfs的类扩展。它看起来像:
public function base(path:string, parent:sprite, callback:function)
{
//this is the child swf path
_path = path;
//parent is the sprtie we want to render the child onto
if(parent != null) doLoad(parent, callback)
}
public function doLoad(parent, callback)
{
var mLoader:Loader = new Loader();
var mRequest:URLRequest = new URLRequest(_path);
//onLoaded is overridden in the child. The override first calls the parent onLoad.
mLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
mLoader.load(mRequest);
}
//this is called from the load complete from above. This is done before the
//child onloaded is done
protected function onLoaded(loadEvent:Event):void
{
_loadedTarget = loadEvent.currentTarget;
_canvas = _loadedTarget.content;
_parentSprite.addChild(_canvas);
}
现在,我们需要显示Swf的大多数类都扩展了这个类。他们看起来像这样
public class child extends base
{
public function child(parent:Sprite, callback)
{
//call base constructor
super("some/path/to/swf", parent, callback);
}
protected override function onLoaded(loadEvent:Event):void
{
super.onLoaded(loadEvent);
....
}
这是基本方案。如果我尝试创建一堆'child'实例而不等待onLoaded函数在前一个'child'上完成,则随机实例根本不会显示。我很快写了上面的代码,它不是compy / paste,所以忽略了简单的错误。上述方法不起作用有什么明显的原因吗?
答案 0 :(得分:2)
可能是因为你在本地范围内声明了你的swf加载器吗?在有机会加载之前,它很可能会超出范围并被垃圾收集。
答案 1 :(得分:1)
这不是一个问题,因为它是一种不同的思维方式。不要以强制性的,程序化的方式思考你的程序(即,做到这一点,做另一个),将你的程序想象成面向对象的事件。 (也就是说,X的完成会触发一个事件,而Y则会注意到这个事件。)我仍然不时地与我的大脑搏斗。
也许事件监听器更符合您的需求?您的Thing
对象可能会在完成某些事件时触发,而代码的其他部分可能会侦听这些事件。
答案 2 :(得分:1)
我认为您的Thing实例没有出现听起来很奇怪。虽然在为Flash编程时通常需要采用异步思维方式,但是您描述这种特殊情况的方式让我觉得您做错了。加载一堆SWF文件并将它们放在舞台上时,Flash应该没有问题,特别是不能只有十个。
只要您使用单独的Loader实例,并将每个加载器添加到stage(或者在Event.COMPLETE事件触发后将其内容添加到其中),理论上您应该能够加载无限数量的SWF文件。浏览器可能会对一次可以存在的连接数有一些限制,因此会将它们排队,但这对Flash Player是透明的,对代码来说更是如此。
如果您使用更真实的代码示例编辑帖子,则可能更容易找到问题。
干杯
答案 3 :(得分:1)
我要去捅这个。我的AS技能虽然有点生疏。
您...
protected function onLoaded(loadEvent:Event):void
{
_loadedTarget = loadEvent.currentTarget;
_canvas = _loadedTarget.content;
_parentSprite.addChild(_canvas);
}
你能......?
var _loadedTarget = loadEvent.currentTarget;
var _canvas = _loadedTarget.content;
要将这些保留在被调用的onLoaded
的范围内,我想没有var,它可能会将这些变量附加到外部作用域,并在每次调用onLoaded时覆盖它们。
还是...?
_parentSprite.addChild(loadEvent.currentTarget._canvas);
因此,您无需设置任何变量并完全消除任何可能的范围问题。
或者也许......?
_loadedTarget[] = loadEvent.currentTarget;
_canvas[] = _loadedTarget[_loadedTarget.length-1].content;
_parentSprite.addChild(_canvas[_canvas[_canvas.length-1]);
您怎么看?
答案 4 :(得分:1)
有一种非常简单的方法可以对异步下载进行排序。只需给Loader一个名字! :)
var pic2loadcount:int = ProjectspictureNames.length;
var ImageLoader:Loader;
for (var counter:int = 0; counter < pic2loadcount; counter++) {
ImageLoader = new Loader();
ImageLoader.name = String(counter);
ImageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE , onProjectImagesLoaded);
ImageLoader.load(new URLRequest(path2pics + ProjectspictureNames[counter]));
}
最后在你的onProjectImagesLoaded函数中,获取名称(onProjectImagesLoaded),转换回int,你就可以排序了! :)
干杯, 德克
答案 5 :(得分:0)
我认为你没有提供足够的信息来获得明确的答案。
听起来你的“Thing”对象有一些异步的初始化,因此执行路径是不可预测的,因为给定的请求可能无序完成。
您可能无法真正管理执行路径,但您可以采取措施管理对象,以便它们至少对用户显示,就好像它们按顺序执行一样。
即将给定对象的索引或引用分配回包含一系列对象的数组,并让它们相互分析以查看哪些已完成,然后相应地运行。
最终这非常愚蠢,你应该考虑一个不同时存在于异步事件和线性执行外观的应用程序设计。
但实际上,要给出明确的答案,您需要告诉我们更多关于您的问题的信息。如果你从正确的角度看它,通常会有一个简单的解决方案。
答案 6 :(得分:0)
听起来不应该是一个问题,但另一方面,我从来没有触发10次调用同时加载sw。
一般情况下,我使用某种加载队列,其中添加了项目(可选择使用优先级让它们按重要性顺序排序),并在队列中的上一项完成加载时加载。
一些一般有用的提示: