转载请注明出处:探索Flash播放器“运行缓慢”的原因及解决方案 - http://as3blog.com/resources/upload-causing-flashplayer-slowly/
最近在实现基于JavaScript和ActionScript的“批量文件上传系统”。感谢SWFUpload这样一个有趣的项目,从前到后ActionScript(AS2)、JavaScript和PHP都已经基本搞定。然而,当我把本地的PHP脚本移到服务器上之后,在上传大文件时,浏览器端的FlashPlayer总是弹出如下警告:
A script in this movie is causing Adobe Flash Player to run slowly. If it continues to run, your computer may become unresponsive. Do you want to abort the script?
大致意思是:“该Flash中有一段单帧脚本导致Flash播放器运行缓慢,如果继续,很可能会引发‘死机’现象”。其中,单帧脚本是指在Flash的一个关键帧中所处理的脚本。
Flash程序,也就是ActionScript,和C++、Java不同,ActionScript在2.0之前的入门门槛非常低,几乎小学生学几天都可以写一个上来溜溜(这并不是一件坏事)。这样一来,产生了不少效率低下的作品,甚至不少Flash动画含有潜在的死循环体(例如点击某个按钮后执行死循环)。虽然我们应该给初学者鼓励,但对于while(true)类似的死循环,则无疑严重破坏了用户体验,甚至会给用户造成不必要的损失。因此,对于编写不规范的ActionScript代码,采取这种措施是非常有必要的。
Adobe官方的解释是“几乎没有一个用户愿意为一个操作等待15秒以上的时间,他们(用户)会认为应用程序出了问题”。因此,Adobe非常“人性化地”在这个“由众多专家调查而得出的15秒”的时间段后给用户一个提示。同时,也给出了一些方法,例如,可以将循环“分摊”到不同的关键帧上。对于载入服务器端数据,如XML文件的案例,当被载入数据超过64k的时候,应将数据分开载入,并以不同的关键帧建立HTTP请求。这么做,比较类似我们在JavaScript中通过setInterval、setTimeout来解决。例如曾经写过一段JavaScript代码来改变整个页面链接的href属性,提供增加alexa排名的可能性。
很遗憾,Adobe忽略了一件事:文件上传。
FileReference和FileReferenceList两个类在Flash8的引入,无疑是Flash在Browser端应用极大的突破之一,曾经困扰Web开发者的Ajax文件上传和批量上传,尤其是对文件类型、大小的客户端检测,如今都能依靠FlashPlayer实现。而且,借助Flash8的External API,可以使ActionScript与JavaScript方便地通信,这样就可以让FlashPlayer在“幕后”完成一切的文件操作,而让DOM(HTML)来展现内容。
然而,恰恰是如此好的功能,却几乎每次都会受到上面提到的“脚本超时保护”的困扰。显然,Adobe官方的解决方案在这里就行不通了。
利用Google搜索,发现无数的人也在询问同样的问题。后来在这篇介绍用Flex实现的批量上传的文章后的评论里面,找到了一个叫做“Timothee Groleau”的哥们的“自问自答”,终于解开了迷团:FlashPlayer在触发并执行用户定义的脚本(就是你编写的ActionScript)时,会重置“脚本超时值”(上文提到的15秒)。这样,我们可在某一个“马甲MovieClip”上绑定一个onEnterFrame事件,让它不断地(逐帧)执行。最简单的做法就是:
_root.onEnterFrame=function(){return false}