JavaScript: JSONP原理详解
1. 什么是jsonp
jsonp全称json with padding,由于浏览器同源策略的限制,网页中无法通过 Ajax 请求非同源的接口数据。但是 <script> 标签不受浏览器同源策略的影响,可以通过 src 属性,请求非同源的 js 脚本。
因此,JSONP 的实现原理,就是通过 <script> 标签的 src 属性,请求跨域的数据接口,并通过函数调用的形式,接收跨域接口响应回来的数据。
由于 JSONP 是通过 <script> 标签的 src 属性,来实现跨域数据获取的,所以,JSONP 只支持 GET 数据请求,不支持 POST 请求。
注意:JSONP 和 Ajax 之间没有任何关系,不能把 JSONP 请求数据的方式叫做 Ajax,因为 JSONP 没有用到XMLHttpRequest 这个对象。
2. 那么有哪些标签可以跨域呢
<img src=""> //图片
<link href=""> //css
<script src=""> //程序
我们可以使用script来帮助我们跨域
2.1 写一个服务端
server.js
//服务端
//引入支持接受请求,返回响应的模块http
const http=require("http");
//创建服务端程序实例
http.createServer(
//每当有客户端发来请求时
//自动调用一下回调函数
(req,res)=>{
var weather = "北京 晴 18-20";
res.writeHead(200,{
"Content-Type":"text/plain;charset=utf-8"
});
//res.write(weather);
res.write(`alert("${weather}")`);
res.end();
}
).listen(80);
测试一下
2.2 写一个客户端
注意客户端不要用服务端的ip,可以在本地写一个,或者另找一台服务器
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JSONP</title>
</head>
<body>
<div id="divCustomers"></div>
<script src="http://47.xxx.xxx.xx/">
</body>
</html>
2.3 测试
访问一下客户端,可以看到他发起的请求,并且也成功弹窗了
2.4 小总结
可以看到,在这个例子中,要返回的实际数据【天气】,被填充到一条合法的js语句中【alert(天气)】,然后被客户端js引擎执行。钻一下牛角尖,现在是data with padding,因为我们还没用到json。
仔细一点,我们会发现,目前的服务端是死的【只能alert】,当我们有多个客户端而带来不同的需求后【你要alert,他要document.write。。。】,目前的服务端代码应付不了
3. 改进【方案二】
所以,我们可以让服务端就产生数据,而不用写什么乱七八糟的js,我们在客户端写自己的函数,那么怎么写呢?
可以看到,在服务端,我就把alert换成了show,而在客户端,我们可以自定义show函数的内容,每次客户端去请求,求回来的是一段show("内容")
的脚本,然后这个脚本被执行,调用我们自己定义好的show函数,实现了一个服务端,多种客户端的需求
4. 改进【方案三,故事的主人公】
怎么还要改进?因为方案二依旧在服务端写死了show函数,我们做个小小的改进,在客户端传个参数进去,在服务端对参数进行解析后,和数据拼接在一起
5. 我要看jsonp
之前的几个例子还没用到json,其实这个不过是一个数据格式而已,原理上都是一样的
server.js
//服务端
//引入支持接受请求,返回响应的模块http
const http=require("http");
const url=require("url");
//创建服务端程序实例
http.createServer(
//每当有客户端发来请求时
//自动调用一下回调函数
(req,res)=>{
var mycallback = url.parse(req.url,true).query.mycallback;
var weather = {
"location":"Beijing",
"weather":"sun",
"temprature":"18-20"
};
weather = JSON.stringify(weather);
res.writeHead(200,{
"Content-Type":"application/json;charset=utf-8"
});
res.write(`${mycallback}(${weather})`);
res.end();
}
).listen(80);
test.html
<!DOCTYPE html>
<!-- 客户端-->
<html>
<head>
<meta charset="utf-8">
<title>JSONP</title>
</head>
<body>
<div id="divCustomers"></div>
<script>
function show(weather){
alert(weather.location);
}
</script>
<script src="http://47.116.97.185/?mycallback=show">
</script>
</body>
</html>
6. jquery 使用jsonp
jQuery 提供的 $.ajax() 函数,除了可以发起真正的 Ajax 数据请求之外,还能够发起 JSONP 数据请求