ajax的跨域一直是一个问题,在网络上流行的几种解决方法外我有了自己的解决方法。
基本思路如下:
1,js向flash发请求
2,flash请求服务器端数据(因为flash的跨域只需要在目标服务器的根目录放一个xml,而不需要写代理)
3,flash取得数据后再回调js的方法,这样就完成了一次异步请求
另外在获取服务器端数据的过程中flash可以实时将已读取的字节数通知给js,这是xmlhttprequest做不到的,也就是能实现完美的loading(有个前提,就是服务器端的xml不能是动态生成,要不只能取得已读取的字节,而取不到总字节);
as代码如下:
package
...
{
import flash.display.Sprite;
import flash.events.*;
import flash.net.*;
import flash.xml.*;
import flash.system.*;
import flash.external.ExternalInterface;
import flash.utils.Dictionary;
import flash.text.TextField;
import flash.utils.Timer;
import flash.text.TextFieldType;
import flash.text.TextFieldAutoSize;
import NT.*;
import flash.utils.*;
public class AjaxHelper extends Sprite ...{
private var config_url:Object=...{
/**//*接口地址1*/
soufun:...{url:"http://xxx?",handle:xml2Obj4sf},
/**//*接口地址2*/
mapabc:...{url:"http://xxx?",handle:xml2Obj4map},
/**//*接口地址3*/
ip:"XMLFile.xml"
};
private var err:String="";//错误
public function errorOut():void ...{
ExternalInterface.call("alert",err);
}
private var cstate:Boolean=false;//状态
public function get cstateOut():Boolean ...{
return this.cstate;
}
var t1:Date;
var t2:Date;
private var output:TextField;
/**//*入口函数*/
public function AjaxHelper() ...{
flash.system.System.useCodePage=true;
t1=new Date();
initJsInterface();
//trace(Core.NetConfig)
cstate=true;
/**//*Debug*/
output = new TextField();
output.y = 0;
output.width = 400;
output.height = 200;
output.multiline = true;
output.wordWrap = true;
output.border = true;
output.text = "Initializing... ";
addChild(output);
//jsInterfaceHandle("sf",null,null);
}
/**//*初始化外部接口*/
private function initJsInterface():void ...{
var _f:Array=[
["nt_AjaxData",jsInterfaceHandle],
["nt_ErrOut",errorOut],
["nt_GetComAreaStr",jsInterfaceHandle]
];
if (ExternalInterface.available) ...{
try ...{
with (ExternalInterface) ...{
for (var i in _f) ...{
addCallback(_f[i][0], _f[i][1]);
}
}
} catch (error:SecurityError) ...{
err+="发生安全错误: " + error.message + " ";
} catch (error:Error) ...{
err+="发生错误: " + error.message + " ";
}
} else ...{
err+="容器不允许接口.";
}
}
/**//*外部接口处理函数*/
private function jsInterfaceHandle(options:Object) ...{
if (options.type in config_url) ...{
output.appendText(String(options.type)+"--type---"+options.callback);
sendHttpRequest(options);
} else ...{
}
//处理待写
}
/**//*发送请求*/
private function sendHttpRequest(options:Object):void ...{
URLLoader.prototype["options"]=new Object;
var loader:URLLoader = new URLLoader();
loader["options"]["type"]=options.type;
loader["options"]["callback"]=options.callback;
if(options.progressback)loader["options"]["progressback"]=options.progressback;
if(options.progressback)loader["options"]["errback"]=options.errback;
configureListeners(loader);
var request:URLRequest = new URLRequest(config_url[options.type].url+(options.para?options.para:"")+"&"+new Date().getTime().toString());
try ...{
loader.load(request);
} catch (error:Error) ...{
err+="无法请求.";
}
}
/**//*设置读取事件委托*/
private function configureListeners(dispatcher:IEventDispatcher):void ...{
var _e:Array=[
[Event.COMPLETE,completeHandler],
[Event.OPEN,openHandler],
[ProgressEvent.PROGRESS,progressHandler],
[SecurityErrorEvent.SECURITY_ERROR,securityErrorHandler],
[HTTPStatusEvent.HTTP_STATUS,httpStatusHandler],
[IOErrorEvent.IO_ERROR,ioErrorHandler]
];
with (dispatcher) ...{
for (var i in _e) ...{
addEventListener(_e[i][0], _e[i][1]);
}
}
}
/**//*数据读取事件委托处理函数*/
private function completeHandler(event:Event):void ...{/**//*完成*/
t2=new Date();
var dd=t2.getTime()-t1.getTime();
output.appendText(dd);
trace("时间差:"+dd);
var loader:URLLoader = URLLoader(event.target);
//trace(loader["options"]["type"]);
var newxml:XML=new XML();
try ...{
newxml=XML(loader.data.toString().replace(""","“").replace("'","‘"));//.replace(/http:///g,"")
} catch (error:Error) ...{
newxml=XML(<root>数据格式错误</root>);
}
var retobj:String=config_url[loader["options"]["type"]]["handle"](newxml);
//trace(retobj);
//output.appendText(retobj.poi[0].x);
ExternalInterface.call(loader["options"]["callback"].toString(),retobj);//回调
}
private function openHandler(event:Event):void ...{/**//*开始*/
//output.appendText("openHandler: " + event);
}
private function progressHandler(event:ProgressEvent):void ...{/**//*过程*/
var loader:URLLoader = URLLoader(event.target);
if(loader["options"]["progressback"])
ExternalInterface.call(loader["options"]["progressback"].toString(),event.bytesLoaded+"/"+event.bytesTotal);
}
private function securityErrorHandler(event:SecurityErrorEvent):void ...{/**//*安全错误*/
err+="securityErrorHandler: " + event;
var loader:URLLoader = URLLoader(event.target);
if(loader["options"]["errback"])
ExternalInterface.call(loader["options"]["errback"].toString(),err);
}
private function httpStatusHandler(event:HTTPStatusEvent):void ...{/**//*HTTP状态*/
err+="httpStatusHandler: " + event;
}
private function ioErrorHandler(event:IOErrorEvent):void ...{/**//*IO错误*/
err+="ioErrorHandler: " + event;
var loader:URLLoader = URLLoader(event.target);
if(loader["options"]["errback"])
ExternalInterface.call(loader["options"]["errback"].toString(),err);
}
/**//*xml转换为Json*/
protected function xml2Obj4sf(xml:XML):Object ...{/**//*sf*/
var _str:String="{hit:[";
for each (var element:XML in xml.hit) ...{
_str+="{";
var _t:String="";
for each (var j in element.child("*")) ...{
_t+='"'+j.name()+'":"'+j+'",';
}
_t=_t.slice(0,_t.length-1);
_str+=_t+"},";
}
if(xml.hit.length>0)
_str=_str.slice(0,_str.length-1);
_str+="]}";
return _str;
}
protected function xml2Obj4map(xml:XML):Object ...{/**//*MAPABC*/
var _str:String="{poi:[";
for each (var element:XML in xml.list.poi) ...{
_str+="{";
var _t:String="";
for each (var j in element.child("*")) ...{
_t+='"'+j.name()+'":"'+j+'",';
}
_t=_t.slice(0,_t.length-1);
_str+=_t+"},";
}
if(xml.list.poi.length>0)
_str=_str.slice(0,_str.length-1);
_str+="]}";
return _str;
}
}
}
import flash.display.Sprite;
import flash.events.*;
import flash.net.*;
import flash.xml.*;
import flash.system.*;
import flash.external.ExternalInterface;
import flash.utils.Dictionary;
import flash.text.TextField;
import flash.utils.Timer;
import flash.text.TextFieldType;
import flash.text.TextFieldAutoSize;
import NT.*;
import flash.utils.*;
public class AjaxHelper extends Sprite ...{
private var config_url:Object=...{
/**//*接口地址1*/
soufun:...{url:"http://xxx?",handle:xml2Obj4sf},
/**//*接口地址2*/
mapabc:...{url:"http://xxx?",handle:xml2Obj4map},
/**//*接口地址3*/
ip:"XMLFile.xml"
};
private var err:String="";//错误
public function errorOut():void ...{
ExternalInterface.call("alert",err);
}
private var cstate:Boolean=false;//状态
public function get cstateOut():Boolean ...{
return this.cstate;
}
var t1:Date;
var t2:Date;
private var output:TextField;
/**//*入口函数*/
public function AjaxHelper() ...{
flash.system.System.useCodePage=true;
t1=new Date();
initJsInterface();
//trace(Core.NetConfig)
cstate=true;
/**//*Debug*/
output = new TextField();
output.y = 0;
output.width = 400;
output.height = 200;
output.multiline = true;
output.wordWrap = true;
output.border = true;
output.text = "Initializing... ";
addChild(output);
//jsInterfaceHandle("sf",null,null);
}
/**//*初始化外部接口*/
private function initJsInterface():void ...{
var _f:Array=[
["nt_AjaxData",jsInterfaceHandle],
["nt_ErrOut",errorOut],
["nt_GetComAreaStr",jsInterfaceHandle]
];
if (ExternalInterface.available) ...{
try ...{
with (ExternalInterface) ...{
for (var i in _f) ...{
addCallback(_f[i][0], _f[i][1]);
}
}
} catch (error:SecurityError) ...{
err+="发生安全错误: " + error.message + " ";
} catch (error:Error) ...{
err+="发生错误: " + error.message + " ";
}
} else ...{
err+="容器不允许接口.";
}
}
/**//*外部接口处理函数*/
private function jsInterfaceHandle(options:Object) ...{
if (options.type in config_url) ...{
output.appendText(String(options.type)+"--type---"+options.callback);
sendHttpRequest(options);
} else ...{
}
//处理待写
}
/**//*发送请求*/
private function sendHttpRequest(options:Object):void ...{
URLLoader.prototype["options"]=new Object;
var loader:URLLoader = new URLLoader();
loader["options"]["type"]=options.type;
loader["options"]["callback"]=options.callback;
if(options.progressback)loader["options"]["progressback"]=options.progressback;
if(options.progressback)loader["options"]["errback"]=options.errback;
configureListeners(loader);
var request:URLRequest = new URLRequest(config_url[options.type].url+(options.para?options.para:"")+"&"+new Date().getTime().toString());
try ...{
loader.load(request);
} catch (error:Error) ...{
err+="无法请求.";
}
}
/**//*设置读取事件委托*/
private function configureListeners(dispatcher:IEventDispatcher):void ...{
var _e:Array=[
[Event.COMPLETE,completeHandler],
[Event.OPEN,openHandler],
[ProgressEvent.PROGRESS,progressHandler],
[SecurityErrorEvent.SECURITY_ERROR,securityErrorHandler],
[HTTPStatusEvent.HTTP_STATUS,httpStatusHandler],
[IOErrorEvent.IO_ERROR,ioErrorHandler]
];
with (dispatcher) ...{
for (var i in _e) ...{
addEventListener(_e[i][0], _e[i][1]);
}
}
}
/**//*数据读取事件委托处理函数*/
private function completeHandler(event:Event):void ...{/**//*完成*/
t2=new Date();
var dd=t2.getTime()-t1.getTime();
output.appendText(dd);
trace("时间差:"+dd);
var loader:URLLoader = URLLoader(event.target);
//trace(loader["options"]["type"]);
var newxml:XML=new XML();
try ...{
newxml=XML(loader.data.toString().replace(""","“").replace("'","‘"));//.replace(/http:///g,"")
} catch (error:Error) ...{
newxml=XML(<root>数据格式错误</root>);
}
var retobj:String=config_url[loader["options"]["type"]]["handle"](newxml);
//trace(retobj);
//output.appendText(retobj.poi[0].x);
ExternalInterface.call(loader["options"]["callback"].toString(),retobj);//回调
}
private function openHandler(event:Event):void ...{/**//*开始*/
//output.appendText("openHandler: " + event);
}
private function progressHandler(event:ProgressEvent):void ...{/**//*过程*/
var loader:URLLoader = URLLoader(event.target);
if(loader["options"]["progressback"])
ExternalInterface.call(loader["options"]["progressback"].toString(),event.bytesLoaded+"/"+event.bytesTotal);
}
private function securityErrorHandler(event:SecurityErrorEvent):void ...{/**//*安全错误*/
err+="securityErrorHandler: " + event;
var loader:URLLoader = URLLoader(event.target);
if(loader["options"]["errback"])
ExternalInterface.call(loader["options"]["errback"].toString(),err);
}
private function httpStatusHandler(event:HTTPStatusEvent):void ...{/**//*HTTP状态*/
err+="httpStatusHandler: " + event;
}
private function ioErrorHandler(event:IOErrorEvent):void ...{/**//*IO错误*/
err+="ioErrorHandler: " + event;
var loader:URLLoader = URLLoader(event.target);
if(loader["options"]["errback"])
ExternalInterface.call(loader["options"]["errback"].toString(),err);
}
/**//*xml转换为Json*/
protected function xml2Obj4sf(xml:XML):Object ...{/**//*sf*/
var _str:String="{hit:[";
for each (var element:XML in xml.hit) ...{
_str+="{";
var _t:String="";
for each (var j in element.child("*")) ...{
_t+='"'+j.name()+'":"'+j+'",';
}
_t=_t.slice(0,_t.length-1);
_str+=_t+"},";
}
if(xml.hit.length>0)
_str=_str.slice(0,_str.length-1);
_str+="]}";
return _str;
}
protected function xml2Obj4map(xml:XML):Object ...{/**//*MAPABC*/
var _str:String="{poi:[";
for each (var element:XML in xml.list.poi) ...{
_str+="{";
var _t:String="";
for each (var j in element.child("*")) ...{
_t+='"'+j.name()+'":"'+j+'",';
}
_t=_t.slice(0,_t.length-1);
_str+=_t+"},";
}
if(xml.list.poi.length>0)
_str=_str.slice(0,_str.length-1);
_str+="]}";
return _str;
}
}
}
使用as3写的,初步功能已经实现,具体效率还是有待实现
html的代码如下
< html >
< head >
< meta http-equiv ="Content-Type" content ="text/html; charset=gbk" />
< title > AjaxHelper </ title >
< script language ="JavaScript" > ...
function thisMovie(movieName) ...{
if (navigator.appName.indexOf("Microsoft") != -1) ...{
return window[movieName];
} else ...{
return document[movieName];
}
}
function sendToActionScript(value) ...{
var _v=new Object();
thisMovie("AjaxHelper").nt_AjaxData(_v);
}
function ascallback (jsonStr) ...{
var kk=eval("("+jsonStr.toString()+")");
thisMovie("AjaxHelper").nt_ErrOut();
alert(kk.hit[0].title);
}
</ script >
</ head >
< body >
< object classid ="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
id ="AjaxHelper" width ="400" height ="200"
codebase ="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab" >
< param name ="movie" value ="AjaxHelper.swf" />
< param name ="quality" value ="high" />
< param name ="bgcolor" value ="#869ca7" />
< param name ="allowScriptAccess" value ="sameDomain" />
< embed src ="AjaxHelper.swf" quality ="high" bgcolor ="#869ca7"
width ="400" height ="200" name ="AjaxHelper" align ="middle"
play ="true" loop ="false" quality ="high" allowScriptAccess ="sameDomain"
type ="application/x-shockwave-flash"
pluginspage ="http://www.macromedia.com/go/getflashplayer" >
</ embed >
</ object >
< div id ="outit" ></ div >
< form name ="form1" onsubmit ="return false;" >
< input type ="text" name ="input" value ="" />
< input id ="qq" type ="button" value ="Send" onclick ="sendToActionScript(this.form.input.value);" />< br />
</ form >
</ body >
</ html >