JavaScript用JSONP跨域请求数据实例详解
前言
最近因为工作需要,需要把爱词霸的每日一句引入到页面上,爱词霸向外开放了API,接口返回json数据,为了让页面更轻巧,我没有用jQuery,而是直接纯js写了一段代码:
<scripttype="text/javascript"> functionhttpGetAsync(theUrl,callback) { xmlHttp=null; if(window.XMLHttpRequest) {//codeforIE7,Firefox,Opera,etc. xmlHttp=newXMLHttpRequest(); } elseif(window.ActiveXObject) {//codeforIE6,IE5 xmlHttp=newActiveXObject("Microsoft.XMLHTTP"); } if(xmlHttp!=null) { xmlHttp.onreadystatechange=function(){ if(xmlHttp.readyState==4&&xmlHttp.status==200) { callback(xmlHttp.responseText); } else { console.error("ProblemretrievingXMLdata"); } } xmlHttp.open("GET",theUrl,true);//trueforasynchronous xmlHttp.setRequestHeader('Access-Control-Allow-Origin','*'); xmlHttp.send(null); } else { console.error("YourbrowserdoesnotsupportXMLHTTP."); } } functionshowIcibaDS(ds_data) { //showdailysentence content=ds_data.content; note=ds_data.note; document.write(content+'<br>'); document.write(note); } httpGetAsync("http://open.iciba.com/dsapi/",showIcibaDS); </script>
运行之后数据并没有获取到,而是出现了如下错误提示:
XMLHttpRequestcannotloadhttp://open.iciba.com/dsapi/.Responsetopreflightrequestdoesn'tpassaccesscontrolcheck:No'Access-Control-Allow-Origin'headerispresentontherequestedresource.Origin'null'isthereforenotallowedaccess.TheresponsehadHTTPstatuscode501.
这就是跨域请求的问题。那么什么是跨域请求呢?浏览器出于安全方面的考虑,采用同源策略(SameoriginPolicy),即只允许与同域下的接口交互。
同域是指:
- 同协议:如都是http或者https
- 同域名:如都是http://konghy.cn/a或http://konghy.cn/b
- 同端口:如都是80端口
也就是说,用户打开了页面:http://blog.konghy.cn,当前页面下的js向http://blog.konghy.cn/XXX的接口发数据请求,浏览器是允许的。但假如向:http://open.iciba.com/xxx发数据请求则会被浏览器阻止掉,因为存在跨域调用。
跨域请求的解决办法就是JSONP(JSONwithPadding).HTML中script标签可以加载其他域下的js,JSONP就是通过script标签加载数据的方式去获取数据当做JS代码来执行,然后再用一个回调函数抽取数据:
<scripttype="text/javascript"> varcur_date=newDate(); document.getElementById("cur_year").innerHTML=cur_date.getFullYear(); functionshowIcibaDS(ds_data) { //showdailysentence content=ds_data.content; note=ds_data.note; ds_p=document.getElementById("iciba_ds") varcontent_span=document.createElement('span'); varnote_span=document.createElement('span'); varbr=document.createElement('br') content_span.innerHTML=content note_span.innerHTML=note ds_p.appendChild(content_span); ds_p.appendChild(br); ds_p.appendChild(note_span); } </script> <scripttype="text/javascript"src="http://open.iciba.com/dsapi/?callback=showIcibaDS"></script>
再查查资料,发现有人做了封装:
functionjsonp(setting) { setting.data=setting.data||{} setting.key=setting.key||'callback' setting.callback=setting.callback||function(){} setting.data[setting.key]='__onGetData__' window.__onGetData__=function(data){ setting.callback(data); } varscript=document.createElement('script') varquery=[] for(varkeyinsetting.data) { query.push(key+'='+encodeURIComponent(setting.data[key])) } script.src=setting.url+'?'+query.join('&') document.head.appendChild(script) document.head.removeChild(script) } jsonp({ url:'http://photo.sina.cn/aj/index', key:'jsoncallback', data:{page:1,cate:'recommend'}, callback:function(ret){ console.log(ret) } })
如果你使用的是jQuery,则可以直接用ajax请求数据:
<scriptsrc="js/jquery-1.11.3.js"></script> <script> $(function(){ $.ajax({ async:true, type:"GET", dataType:'jsonp', jsonp:'callback', jsonpCallback:'callbackfunction', url:"http://open.iciba.com/dsapi/", data:"", timeout:3000, contentType:"application/json;utf-8", success:function(data){ console.log(data); } }); }) </script>
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。
参考资料
https://www.nhooo.com/article/75669.htm
https://zhuanlan.zhihu.com/p/22600501