ExternalInterface SecurityError国产浏览器问题
使用swfobject在页面中嵌入SWF是件很方便的一件事情,但是涉及ActionScript和JavaScript通信时,还是需要注意一些问题。
1. 跨域的问题
通常资源文件(静态组件)和HTML文件不在同一个服务器下,这时候ActionScript和JavaScript跨域通信时就需要做一些处理。我们需要在ActionScript中这样编写:
Security.allowDomain('siteA.com');
如果涉及https连接,还会加上:
Security.allowInsecureDomain('siteA.com');
2. ExternalInterface抛出SecurityError问题
在Flash启动时就调用ExternalInterface方法在浏览器下会经常出现SecurityError异常的。特别时在TT浏览器,360浏览器,世界之窗浏览器,傲游浏览器等国产货下,有些杯具就会出现。
下面进行4种case的测试(都是用swfobject动态嵌入SWF的):
- 1. 立马呼叫ExternalInterface的call和addCallback方法
- 在IE内核的国产浏览器下,第二次加载时无法接受到js的呼叫
- 2. 立马呼叫ExternalInterface的addCallback方法,延迟呼叫call方法
- 在IE内核的国产浏览器下,第二次加载时,addCallback方法抛出异常,无法接受到js的呼叫。
- 3. 立马呼叫ExternalInterface的call方法, 延迟呼叫addCallback方法
- 在IE内核的国产浏览器下,第二次加载时,call方法抛出异常。
- 4. 延迟呼叫ExternalInterface的call和callback方法
- 兼容各个浏览器
所以,最终相对稳定的代码大概是这样的:
//change to a real domain
Security.allowDomain('*');
Security.allowInsecureDomain('*');
var timeId = setTimeout(function(){
try{
ExternalInterface.addCallback('fromJS', fromJS);
}catch(e1:SecurityError){}
try{
ExternalInterface.call('fromAS');
}catch(e2:SecurityError){}
clearTimeout(timeId);
}, 50);
除了这个方法之外,还有一个更简洁的方法,就是每次请求swf时加上一个时间戳以示区别。但是它就没有利用到缓存的优势。
swfobject.embedSWF('source.swf'+'?timestamp='+new Date(), 'element_id',
'width', 'height', 'required-version');