最近在網路上看了很多JS跨域訪問的解決方案。。比較了一下,大致上有這麼兩種:
第一個是使用內嵌的iframe,由於iframe能夠訪問外部域,因此,便實現了一種簡單的跨域訪問。但是這裡存在著一個問題,那就ParentWindow和childWindow之間不能直接進行互動,因為在跨域的情況下,由於安全性的原因,這種互動是被拒絕的。。這時候,人們便想到了使用anchor hash來實現。因為改變一個網頁的anchor hash並不會使網頁重新載入,,從而使網頁的狀態得到了保持。而網頁本身可以通過一個計時器偵聽自己hash的變化,從而改變自己的狀態。。說白了,其實就是使用anchor hash來進行跨域的互動。。
這種方法現在用的很少,下面介紹另一種比較流行的辦法:JSONP
這種方式實際上是使用script標籤來進行跨域的訪問。它的原理實質上就是通過script標籤來對javascript文檔的動態解析來說實現。。當我們要求實現AJAX跨域訪問時,必須忘掉方便的XMLHttpRequest,而只使用動態產生的script,下面的一個例子是對JSONP方法的一個封裝,來類比ajax:(使用script的一個限制是它只支援get請求,這就限制了它只能傳遞少量的資料)
var XssHttpRequestCount=0;<br />var XssHttpRequest=function(){<br /> this.requestID='XSS_HTTP_REQUEST_'+(++XssHttpRequestCount);<br />}<br />XssHttpRequest.prototype={<br /> url:null,<br /> scriptObject:null,<br /> responseJSON:null,<br /> status:0,<br /> readyState:0,<br /> timeout:30000,<br /> onreadystatechange:function(){},<br /> setReadyState:function(newReadyState){<br /> if(this.readyState<newReadyState||newReadyState==0){<br /> this.readyState=newReadyState;<br />this.onreadystatechange();<br /> }<br /> },<br /> open:function(url,timeout){<br /> this.timeout=timeout||3000;<br />this.url=url<br /> +((url.indexOf('?')!=-1)?'&':'?')<br /> +'XSS_HTTP_REQUEST_CALLBACK='<br /> +this.requestID+'_CALLBACK';<br />this.setReadyState(0);<br /> },<br /> send:function(){<br /> var requestObject=this;<br />this.scriptObject=document.createElement('script');<br />this.scriptObject.setAttribute('id',this.requestID);<br />this.scriptObject.setAttribute('type','text/javascript');<br />var timeoutWatcher=setTimeout(function(){<br /> window[requestObject.requestID+'_CALLBACK']=function(){};<br /> requestObject.scriptObject.parentNode.removeChild(requestObject.scriptObject);<br /> reqeustObject.status=2;<br /> requestObject.statusText='Timeout after '+requestObject.timeout+' milliseconds.';<br /> requestObject.setReadyState(2);<br /> requestObject.setReadyState(3);<br /> requestObject.setReadyState(4);<br />},this.timeout);<br /> window[this.requestID+'_CALLBACK']=function(JSON){<br /> clearTimeout(timeoutWatcher);<br /> requestObject.setReadyState(2);<br /> requestObject.setReadyState(3);<br /> requestObject.responseJSON=JSON;<br /> requestObject.status=1;<br /> requestObject.statusText='Loaded'.<br /> requestObject.setReadyState(4);<br /> }<br /> this.setReadyState(1);<br /> this.scriptObject.setAttribute('src',this.url);<br /> var head=document.getElementsByTagName('head')[0];<br /> head.appendChild(this.scriptObject);<br /> }<br />}</p><p>function getXssRequestObject(url,options){<br /> var req=new XssHttpRequest();<br /> options=options||{};<br /> options.timeout=options.timeout||30000;<br /> req.onreadystatechange=function(){<br /> //這裡類比ajax中的請求狀態<br /> switch(req.readyState){<br /> case 1:<br /> //載入中<br /> if(options.loadListener){<br /> options.loadListener.apply(req,arguments);<br /> }<br /> break;<br /> case 2:<br /> //載入完成<br /> if(options.loadedListener){<br /> options.loadedListener.apply(req,arguments);<br /> }<br /> break;<br /> case 3:<br /> //互動<br /> if(options.interactiveListener){<br /> options.interactiveListener.apply(req,arguments);<br /> }<br /> break;<br /> case 4:<br /> //完成<br /> if(req.status==1){<br /> if(options.completeListener){<br /> options.completeListener.apply(req,arguments);<br />}<br /> }<br /> else{<br /> if(options.errorListener){<br /> optiosn.errorListener.apply(req,arguments);<br />}<br /> }<br /> break;<br /> }<br /> };<br /> req.open(url,options.timeout);<br /> return req;<br />}</p><p>function xssRequest(url,options){<br /> var req=getXssRequestObject(url,options);<br /> return req.send(null);<br />}