`

JS 与 AS 交互及效率对比

阅读更多

 

    想象下有这样的业务场景,我用flash实现了文件的上传,上传完之后,我们可能需要在页面上弹个提示框告诉用户上传结果。我们不可能把所有东西都放在flash里完成,因为那样flash的文件会加大,而且也不够灵活,因为flash是需要编译后才能跑的,所以我们最好把能用js实现的都剥离出来,让flash只做一些核心的功能。这样,我们就需要用as去调用js。同样的,如果js操作完了想通知到flash,就需要用js去调用flash中的as方法。此时可以看作as是js增强的一部分。

     不管是as调用js,还是js调用as,其实都围绕ExternalInterface。ExternalInterface 类是外部 API,这是一个在 ActionScript 和 Flash Player 容器之间实现直接通信的应用程序编程接口。当然插入flash的html标签中<param name='allowScriptAccess' value ='always' /> 不能为never,如果设置成never一下所有都是空谈了,一般情况下都设置成always,它也可以接受具体的domain或者IP。

     ExternalInterface有两个提供相互调用的静态方法:
     /**
      * @param functionName {String} 
      * @param closure {Function}
      * @usage 将 ActionScript 方法注册为可提供外部js调用。
      */
     addCallback(functionName:String, closure:Function):void 

     /**
      * @param functionName {String} 
      * @param arguments {Function} (optional)
      * @usage 调用页面上的js。
      */
     call(functionName:String, ... arguments):*
 

Example 1:
假如页面上有一个叫sayHi的js函数, 如下:
window.onload=function (){
     function sayHi(){alert('Hello JS')}
}
 
要在flash中调用这个函数,可以用两个办法:
navigateToURL(new URLRequest( 'javascript:sayHi()' ), '_self'); //实际上打开一个新窗口,只不过url是javascript:sayHi(),这是土鳖方法
ExternalInterface.call( 'sayHi');// 用到了ExternalInterface类,这种方法也是adobe推荐的做法
 
运行结果,发现两个都没法执行,这是因为flashplayer只能看到页面上全局的javascript,所以要想能让flash拿到这个js函数,必须暴露出来。修改代码在运行
window.onload=function (){
     function sayHi(){alert('Hello JS')}
     window['sayHi'] = sayHi;
}
 
代码成功运行了,于是,我们可以总结出一点:提供给flash调用的js函数必须是全局的,获取寄宿在全局对象上的。
     有时候我们只用到了flash的功能,而没用到它的UI所以想把flash隐藏,比如做一个即时通讯的东西,只有通讯部分用到了flash, 当尝试把flash设置成display:none的时候,发现js与as根本无法相互调用,所以说如果需要隐藏flash,设置css是行不通的,可以设置它的宽高为1px来解决。

     如果是想在js中调用as方法,需要用ExternalInterface.addCallback注册as方法,让他暴露在flash实例上。比如flash中有这样的方法:
private function sayHi():void{
     Alert.show('Hi As');
}
External.addCallback('jsSayHi', sayHi);
 
这样就可以在js中执行jsSayHi这个代理方法,它会去执行sayHi这个as方法。jsSayHi这个代理方法会寄宿在flash dom元素上,作为dom元素的方法。
window.onload=function (){
     document.getElementById('flashId').sayHi();
}
 
测试一下,还是发现了问题,有时候能正常运行,但有时候会抛出错误:Uncaught TypeError: Object #<HTMLObjectElement> has no method 'jsSayHi',这是因为即使当前页面onload了,但是flash中的代码初始化还没运行完,所以还没有把代理方法注册到flash dom元素上。(查看实例3-jscallas_b.html)

     那么,flash有没有类似domready的时间点呢?查看好多资料没看到,但是可以模拟一个。我们认识当flash能正常调用页面上的js时,flash能正常跟js进行交互。我们在页面上定义一个flashready函数,让flash回调。
function flashready(){
     document.getElementById('flashId').jsSayHi(); 
     alert('flash is ready');    
}
 

ExternalInterface.call( 'flashready' );
 

     这样js对as的调用就能100%的成功了。

     对于静态资源往往会放在cdn上,比如有一台cdn域名是cdn.com,而主域名确是xxx.com,这样就出现了跨域的问题。浏览器的安全策略导致ajax不能正常的跨域请求,flash player的安全策略同样不允许flash跨域请求和调用。当遇到跨域时,flash player会抛出“安全沙箱冲突错误”。其实flash是支持跨域的,只不过要做一些设置。

     如果是跨域脚本执行,flash中有Secure.allowDomain(somedomain1, somedomain2)来允许制定的url请求,somedomain也可以是通配符"*",也就是不做源限制。如果flash的url是https的链接,则需要用allowInsecureDomain()来做沙箱桥,但如果当前html也是https,那不需要用它。尽量避免使用allowInsecureDomain会削弱https的安全性。但是在一些国产浏览器中,比如腾讯TT,遨游,360等浏览器中,经常会遇到第一次进来js能正常调用flash中的as,但是当刷新一次页面,发现调用不成功了。这是因为第二次访问的时候,flash被缓存到了本地,这些浏览器破坏了flash和浏览器的某种约定,所以导致他们不能相互调用。
     这个问题有两个做法:一、当flash文件很小时,用无缓存的方式解决,比如请求后面加随机数。二、延迟Flash的初始化功能。通过将Flash的ExternalInterface.addCallback初始化时间延后一些(比如500ms),就可以解决这个问题。
     顺便提一下,如果是flash中的http/socket等跨域请求,则需要一个叫crossdomain.xml的策略文件。这个文件放在服务器上,如果是跨域请求,在请求真实地址之前会去请求这个安全策略文件。
<cross-domain-policy>
<allow-access-from domain=”*.xxx.com”/>
<allow-access-from domain=”*.xxx.net”/>
<allow-access-from domain=”*.xxxcdn.com”/>
<allow-access-from domain=”*.allyes.org”/>
</cross-domain-policy>
 

     有人可能会考虑js与as之间频繁的相互调用会带来性能问题。简单的做了下测试
测试代码如下:

function flashready(){
       var swf = document.getElementById('performance'), //方案1
       //var swf = {'test':function(){return 1}}, //方案2
			test = swf.test,               
			i = 10000;    
							
	   var start = + new Date;
	   while(i--){
			test.call(swf);
	   }
	   alert(+ new Date - start);                 
}
 
flashready是一个全局的,提供给flash初始完回调的函数。注意代码中把获取flash dom放到一个变量里,因为dom操作本身开销大,如果不这么做会影响精确性。实验结果如下:
测试项目(测10次取平均值) chrome 19 firefox 9 ie6 ie7 ie8 ie9
js调用as 10000次耗时(方案1) 1747ms 1083ms 360ms 557ms 485ms 401ms
js调用js 10000次耗时(方案2) 1ms 4ms 15ms 31ms 15ms 0ms

观察结果,虽然说js与as执行的执行要比js与js之间慢很多很多,但是勉强还是能接受的,即使是最慢的chrome,平均调用一次也只需要0.17ms,但还是要尽量减少相互调用的次数,就像减少http请求一样。

综上所述,js与as的安全交互必须满足:
  1. <param name='allowScriptAccess' value ='always' />   
  2. flash不能隐藏(display:none)  
  3. 等被调用方初始化完成再去调用,as中可以用ExtercalInterface.call('flashready')来告知初始化完成
  4. 跨域执行,必须在flash中设置Secure.allowDomain或者Secure.allowInsecureDomain
最后做下小广告,欢迎加JS&PHP群(166643291)一起进步。

 

分享到:
评论

相关推荐

    AS2语言参考

    1. **基础语法**:AS2具有与JavaScript相似的基本语法结构,包括变量声明(var)、数据类型(Number, String, Boolean, Object等)、运算符(算术、比较、逻辑、位操作等)以及流程控制语句(if...else, switch, for...

    greensock-v12-as3

    - **与其它第三方库比较**:与Ease.js或Tweener等相比,GreenSock AS3提供了更多高级功能,如时间线控制,更适合专业开发者。 总之,"greensock-v12-as3"是AS3开发者的重要工具,它简化了动画的创建过程,提高了...

    flash/as3 3D 版 SNS社交游戏源码

    在AS3中,这可能通过比较物体在视口中的Z坐标或使用深度缓冲(Z-Buffer)实现。深度缓冲是一种像素级别的渲染技术,用于存储每个像素的深度值,以决定哪个物体应该在前景,哪个在背景。 再者,"光照系统"是3D游戏...

    Android-pareto.js-非常小直观和快速实用工具类集合的JavaScript库

    `pareto.js` 是这样一个小型、直观且高效的JavaScript库,它集合了一系列实用工具类,旨在简化开发者的工作流程,提高代码的可读性和执行效率。 **库的特性** 1. **小巧轻便**:`pareto.js` 的大小极小,这使得它...

    Notas_JS

    标题 "Notas_JS" 暗示这是一个关于 JavaScript 的学习项目,可能是个人笔记或练习集。描述中的 "Projeto Para treinar as habilidades em js" 表明这是一系列用于提升 JavaScript 编程技能的练习或教程。标签 ...

    基于vue可视化拖拽编辑,页面生成工具 提升前端开发效率,可集成至移动端项目作为通过定义 JSON 直接生成 UI 界面

    "基于Vue可视化拖拽编辑,页面生成工具"是一种利用Vue.js技术构建的工具,它旨在提升前端开发效率,允许开发者通过直观的拖放操作在界面上创建和编辑页面布局,然后将这些布局转换为JSON数据。这个过程不仅简化了UI...

    JavaScript 和 Python 中的异步文件下载.docx

    本文将深入探讨JavaScript和Python中的异步文件下载机制,并通过实际示例进行对比分析。 首先,我们来看JavaScript的情况。JavaScript作为Web开发的核心语言,其异步处理主要依赖于回调函数、Promise和async/await...

    adobe flash开发官方库

    2. **JSON支持**:库中包含了JSON(JavaScript Object Notation)的序列化和反序列化功能,允许数据在AS3和服务器之间以JSON格式交换,提高了数据交互的效率。 3. **加密与哈希**:AS3CoreLib提供了MD5和SHA-1等...

    colliusion-as:所有代码

    在实际应用中,"colliusion-as"项目可能还会包含测试用例、性能优化以及与其他库(如Phaser、Three.js等)的集成。开发者可能需要根据具体需求来调整算法,确保其在不同场景下的效率和准确性。总之,理解并熟练掌握...

    背景及文字颜色的改变.rar

    2. JavaScript:可以动态修改颜色,比如根据时间改变背景颜色,或响应用户交互事件。 3. UI库和框架:许多UI库(如Bootstrap)和前端框架(如React)提供了预设的色彩方案,简化了颜色管理。 六、无障碍性 遵循WCAG...

    Domino LS JSON

    6. **示例应用**:在实际应用中,LotusScript与JSON的结合可能用于调用RESTful API、与Web服务交互、存储和检索结构化的数据等场景。 总之,通过内置的JSON支持,LotusScript开发者可以充分利用JSON的优势,提高...

    Cars.rar_easypano flex_汽车360

    6. **Flash和HTML5的比较**:由于Flash已经逐渐被HTML5取代,可以讨论如何将这样的项目迁移到HTML5/CSS3/JavaScript平台,例如使用A-Frame或Three.js等库。 通过学习和实践这些知识点,开发者可以掌握创建类似360度...

    ajax自用笔记非常不错

    ### Web2.0与Web1.0对比及Ajax在其中的角色 #### Web2.0概述与特征 Web2.0代表了互联网发展的新阶段,它更加强调用户的参与度、互动性和个性化。与Web1.0相比,Web2.0不仅关注内容的提供,更注重用户如何使用这些...

    当今主流AJAX框架Dojo教程

    本文将详细解析如何利用Dojo框架与Struts2进行交互,实现数据的异步加载和处理。 ### 一、Dojo框架概述 Dojo是一个开源的JavaScript库,旨在简化HTML网页中复杂用户界面的开发。它提供了许多高级特性,如事件处理...

    实现高级表格根据某列文本、数值排序

    在IT行业中,高级表格的实现通常涉及到数据管理与可视化,特别是在大数据处理和用户交互界面设计时。本话题聚焦于如何实现在表格中根据特定列的文本或数值进行排序,这是一项关键功能,使得用户能够快速查找和理解...

    实现统计功能的折线图和柱型图

    在JavaScript中,有D3.js、Chart.js和Highcharts等。以Python的matplotlib为例,创建一个简单的柱型图需要以下步骤: 1. 导入matplotlib库:`import matplotlib.pyplot as plt` 2. 准备数据:包括x轴和y轴的值 3. ...

    ActionScript 3.0 开发人员指南 (AS3开发帮助文档)

    JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。ActionScript 3.0提供了原生的JSON支持,包括序列化和反序列化的功能。 **定义自定义JSON行为** 对于复杂的数据结构,可以定义自定义的行为来控制...

    UploadPlugIn上传控件

    在文件上传场景中,通过计算上传文件的MD5值并与服务器端的值进行对比,可以有效检测文件在传输过程中是否被篡改或损坏。然而,作者未能找到一种理想的、在Flex环境中实现MD5校验的方法。 在Flex中实现MD5校验,...

    jquery-1.1.3 效率提高800%

    Safari 2 3575ms 475ms 753% Opera 9.1 3196ms 326ms 980% Average improvement: 867% &lt;br&gt;下表为jQuery1.1.3与常用的一些JS库选择器的对比: Browser Prototype jQuery Mootools Ext Dojo ...

    Python-pyecharts一个基于百度Echarts的Python图表绘制库

    Echarts是一款用JavaScript实现的开源可视化库,而`pyecharts`则为Python程序员提供了与Echarts接口的桥梁,使得在Python环境中构建图表变得十分便捷。 1. **安装与导入** 安装`pyecharts`可以通过pip命令轻松完成...

Global site tag (gtag.js) - Google Analytics