封装-Jsonp
Jsonpjsonp是什么?为什么使用jsonp?原理---jsonp的通俗讲解案例---使用script的src获取跨域数据
封装Jsonp案例---获取qq.com中的城市信息与天气信息
Jsonp
jsonp是什么?
通过script标签中的src属性没有同源限制的方法进行获取数据
即通过script标签来跨域获取数据,名为JSON with Padding, 或者就叫JSONP。JSONP的原理很简单,但需要服务器端给予相应配合。 大致来说,JSONP的实现思路就是在客户端编程时作好使用JSON数据的准备,然后再通过圆括号将这些数据括起来以创建一条有效的JavaScript语句(可能是一次有效的函数调用)。
也就是说,客户端可以使用一个用于命名jsonp的查询参数来决定可以获取的数据。最简单的情况下,如果jsonp参数为空,则返回的数据就是被括在圆括号中的JSON
为什么使用jsonp?
浏览器安全模型规定,XMLHttpRequest、框架(frame)等只能在一个域中通信。 从安全角度考虑,这个规定很合理; 但是,也确实给分布式(面向服务、混搭等等本周提到的概念)Web开发带来了麻烦。
本地代理: 需要一些硬件设施(没有服务器的客户端无法运行),并且带宽和潜伏时间也要加倍(远程服务器-代理服务器-客户端)。
Flash: 远程主机中需要部署一个crossdomain.xml文件,而且,Flash作为一门专有技术,其前途尚不明朗;换句话说,开发人员很可能要学习一种目标不确定的编程语言。
Script标签: 无法确切知道内容是否有效,没有标准的实现方法,又可能被认为是一种“安全风险”。
原理—jsonp的通俗讲解
使用script 的src属性没有同源限制,跨域名获取数据的一种方法
案例—使用script的src获取跨域数据
<script type="text/javascript">
function jp(data) {
console.log(data);
}
</script>
<script src="https://apis.map.qq.com/ws/location/v1/ip?callback=jp&key=CAABZ-AVSAQ-RDR5L-GTBDJ-HLA4O-A5FDB&output=jsonp" ></script>
封装Jsonp
原理:使用script 的src属性没有同源限制,跨域名获取数据的一种方法动态的创建script标签,使用src属性来进行跨域获取数据其中使用有Promise,异步
function jsonp(url
,option
={}) {
var jp
= option
.jp
||"callback";
var callback
= option
.callback
||"jp";
return new Promise((resolve
,reject
) => {
if(url
.indexOf(jp
)==-1){
url
+= "&"+jp
+"="+callback
;
}
var p1
= url
.indexOf(option
.jp
);
var p2
= url
.indexOf("&",p1
);
p2
== -1 ? p2
= url
.lenght
;
callback
= url
.slice(p1
+jp
.length
+1,p2
);
window
[callback
]=function(data
){
document
.head
.removeChild(script
);
resolve(data
);
}
let script
= document
.createElement("script");
script
.src
= url
;
document
.head
.append(script
);
script
.onerror = function(e
){
document
.head
.removeChild(script
);
reject(e
)}
})
}
案例—获取qq.com中的城市信息与天气信息
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<p id="city" ></p>
<img src="" id="img" alt="">
<p id="weather"></p>
</body>
<script type="text/javascript">
function jsonp(url,option={}) {
var jp = option.jp||"callback";
var callback = option.callback||"jp";
return new Promise((resolve,reject) => {
if(url.indexOf(jp)==-1){
url += "&"+jp+"="+callback;
}
var p1 = url.indexOf(jp);
var p2 = url.indexOf("&",p1);
p2 == -1 ? p2 = url.lenght : '';
callback = url.slice(p1+jp.length+1,p2);
window[callback]=function(data){
document.head.removeChild(script);
resolve(data);
}
let script = document.createElement("script");
script.src = url;
document.head.append(script);
script.onerror = function(e){
document.head.removeChild(script);
reject(e)
}
})
}
var url1 = "https://apis.map.qq.com/ws/location/v1/ip?key=CAABZ-AVSAQ-RDR5L-GTBDJ-HLA4O-A5FDB&output=jsonp";
var url2 = "https://wis.qq.com/weather/common?weather_type=observe|forecast_24h|air&source=pc&callback=jp";
jsonp(url1)
.then(res=>{
url2 = url2+`&province=${res.result.ad_info.province}&city=${res.result.ad_info.city}`;
city.innerHTML=res.result.ad_info.city;
return jsonp(url2);
})
.then(res=>{
weather.innerHTML=res.data.observe.degree+"℃";
img.src="https://mat1.gtimg.com/pingjs/ext2020/qqindex2018/dist/img/weather/"+res.data.observe.weather_code+".svg";
})
</script>
</html>