前言
与跨域相反的是同源,浏览器出于安全性考虑都会选用同源策略,主要是限制cookie、DOM、JS对象的获取,此外AJAX请求也不能发送。显然同源策略限制了前端的向外拓展的能力,实际应用中可以使用跨域请求来实现对外拓展。跨域顾名思义就是请求域名不同,如果考虑到细节,同一域名不同端口、同一域名不同协议也算跨域。举个例子,当前项目的请求是自己的公司域名下的链接,但是又想引用百度或者其他开放的API,此时的情景就是跨域。而跨域请求的解决方案以JSONP最为方便快捷。
JSONP跨域原理
前端常用AJAX请求来实现不刷新页面方式向服务器请求数据,但它受浏览器同源策略的影响而无法实现跨域请求。然而script标签src属性的引用却是不受跨越限制的,基于此可以发送跨域请求,服务端不再是返回JSON格式的数据,而是返回一段调用某个函数的js代码,在src中进行了调用。
原生js方式实现
<script>
//动态创建script标签
function jsonp(url){
var script = document.createElement('script');
script.src = url;
document.body.append(script);
document.body.removeChild(script);
}
function callbackfun(){
//处理jsonp跨域请求返回的结果
}
var url='http://xxx.com/jsonp?callback=callbackfun';
jsonp(url);
</script>
Jquery实现
$.ajax({
url: 'http://xxx.com/jsonp?callback=callbackfun'; //跨域请求链接
type: 'get', //http请求方式
dataType: 'jsonp', // 设置请求方式为jsonp
jsonpCallback: "callbackfun", // 定义响应跨域请求的回调函数
data: {}
});
JSONP跨域请求百度API 获取天气预报信息效果
如图,百度API提供了当前城市的天气信息,地理位置是根据浏览器自动获取的。不知道为什么,就想码个红包上去,可能是程序员生活太单调了吧,唉,竟然都码上了,掏出手机支付宝扫一扫呗,从此我们有了半毛钱的关系(*^__^*)

JSONP跨域请求样例
JSONP跨请请求拓展了前端获取资源的能力,在常规软件设计中我们不免会调用一些开放平台的API来丰富我们页面的内容,JSONP跨域请求是个不错的选择,下面我们利用JSONP跨域请求来实现获取天气预报信息的界面,样例很简单,请求链接为百度地图开放的API。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
body, html,#mainbody {
width: 100%;
height: 100%;
overflow: hidden;
margin:0;
font-family:"微软雅黑";
background: url(./weatherbackground.jpg) no-repeat;
background-size: cover;
}
#mainbody{
width: 100%;
height: 100%;
border-radius: 10px;
}
#weather{
width: auto;
height: 800px;
}
#navi{
width: 100%;
height: 50px;
background:rgba(242,242,242,0.1);
border-radius: 15px;
text-align: center;
padding: 18px;
margin-bottom: 20px;
font-size: 24px;
color: #EEB217;
}
#weathercontent{
/*margin-top:15px;*/
width: 450px;
height: 550px;
float: left;
border-radius: 15px;
background:rgba(242,242,242,0.5);
text-align: center;
padding: 10px;
font-size: 24px;
color: #EEB217;
}
#weathertipid{
margin-top:20px;
width: auto;
height: 550px;
margin-left: 530px;
border-radius: 15px;
background:rgba(242,242,242,0.5);
text-align: left;
padding: 10px;
font-size: 24px;
color: #EEB217;
}
#weathertips{
}
.tipindex{
font-size: 18px;
color: #EEB217;
}
.tipitem{
font-size: 16px;
color: #330000;
}
#footer{
width: 100%;
height: 220px;
border-radius: 15px;
background:rgba(242,242,242,0.01);
text-align: center;
position:fixed;
left:0px;
bottom:0px;
}
</style>
<script type="text/javascript" src="https://api.map.baidu.com/api?v=2.0&ak=hupWCRW9pUS1mjqYheUDlDgEqbAmlSMW&callback"></script>
<title>JSONP请求天气信息</title>
</head>
<body>
<div id="mainbody">
<div id="weather">
<div id="navi">您所在的城市天气情况</div>
<div style="width: auto; height: 800px;">
<div id="weathercontent">
<div id="weathercity" style="height: 50px;margin-bottom: 20px;color: #33A0E8;"></div>
<div id="weatherdate"></div>
<div id="weatherimg" style="width: auto; height:auto;">
<div style="margin-left: 30px; width: 150px;margin-bottom: 20px; float: left;">
<div style="font-size: 18px;margin: 15px; color: #330000;" >白天</div>
<img id="dayimg" width="128px" height="128px" style="opacity:0.6;border-radius: 15px;"></img>
</div>
<div style="right: 30px;margin-bottom: 20px;padding-top: 1px;">
<div style="font-size: 18px;margin: 15px; color: #330000;" >夜晚</div>
<img id="nightimg" width="128px" height="128px" style="opacity:0.6;border-radius: 15px;"></img>
</div>
</div>
<div id="weatherinfo">
<span></span>
<span></span>
<span></span>
<span></span>
</div>
</div>
<div id="weathertipid">
<div id="weathertips">
<div style="height: 50px;margin-bottom: 20px; text-align: center; color: #33A0E8;">温馨提示</div>
<div>
<span class="tipindex">穿衣指数:</span>
<p class="tipitem"></p>
</div>
<div>
<span class="tipindex">洗车指数:</span>
<p class="tipitem"></p>
</div>
<div>
<span class="tipindex">感冒指数:</span>
<p class="tipitem"></p>
</div>
<div>
<span class="tipindex">运动指数:</span>
<p class="tipitem"></p>
</div>
<div>
<span class="tipindex">紫外线强度指数:</span>
<p class="tipitem"></p>
</div>
</div>
</div>
</div>
</div>
<div id ="footer">
<div>
<img src="hongbao.png" width="150px" height="180px" style="padding-left: 100px">更多精彩</img>
</div>
<div>
<a href="https://blog.youkuaiyun.com/dosthing/" style="color: #EEB217; font-size: 20px; margin-right: 50px">优快云 博客</a>
<a href="https://github.com/dosthing/" style="color: #EEB217; font-size: 20px; margin-left: 50px;">Github </a>
</div>
</div>
</div>
<script type="text/javascript">
//用百度地图API获得当前所在城市
var map = new BMap.Map('map');
var myCity = new BMap.LocalCity();
var localcity;
myCity.get(getcityname); //使用API取得当前城市名
function getcityname(result){
var url = 'https://api.map.baidu.com/telematics/v3/weather?&ak=hupWCRW9pUS1mjqYheUDlDgEqbAmlSMW&output=json&callback=callbackfun&location=';
localcity = result.name.replace('市', '');
url = url + encodeURI(localcity);
jsonp(url);
}
//jsonp请求接口,并处理相应内容
function jsonp(url){
var script = document.createElement('script');
script.src = url;
document.body.append(script);
document.body.removeChild(script);
}
function callbackfun(response){
//处理jsonp跨域请求返回的结果
var doc = document;
//console.log(response);
//console.log(response.results[0].currentCity);
//console.log(response.results[0].weather_data[0].date);
doc.getElementById('weathercity').innerHTML = response.results[0].currentCity + '市';
doc.getElementById('weatherdate').innerHTML = response.results[0].weather_data[0].date;
var span = doc.getElementById('weatherinfo').getElementsByTagName('span');
var p = doc.getElementsByTagName('p');
var result = response.results[0].index;
var today = response.results[0].weather_data[1];
var daypic = doc.getElementById('dayimg');
daypic.src = today.dayPictureUrl;
var nightpic = doc.getElementById('nightimg');
nightpic.src = today.nightPictureUrl;
//console.log(today);
var i = 0;
for (var index in result){
for (var item in result[index]){
if (item == 'des'){
p[i].innerHTML = result[index][item];
console.log(result[index][item]);
i++;
}
}
}
span[0].innerHTML = today.weather;
span[1].innerHTML = today.wind;
span[2].innerHTML = today.temperature;
span[3] = response.results[0].pm25;
}
</script>
</body>
</html>
总结
JSONP的应用拓宽了前端请求的能力,合理利用JSONP,可以是我们的应用内容更加精彩,尽管JSONP优势众多,但是还是应该合理引用,因为过多引用外部的API很难保证API提供商的服务器畅通无阻,从而影响页面加载效果,欢迎访问我的GitHub学习交流。