- 一个域名地址的组成:
- 当协议、子域名、主域名、端口号任意一个不相同时,都算作不同域,不同域之间相互请求资源,就算做“跨域”。由于浏览器同源策略的限制,非同源下的请求,都会产生跨域问题。
- 使用jquery的jsonp可以发起跨域请求,下面来探究下他的原理及使用。
首先看下如何使用<script src="">来完成一个跨域请求:
普通的ajax请求是会发生跨域问题的,但是img的src,a的href,script的src却可以发起任意网址的请求并接收到响应,于是我们首先利用script的src来完成一个跨域请求。
客户端:
<script>
function show(weather){
document.write(weather)
}
//show('返回的数据');
</script>
<!--用请求参数将函数名传递给服务器。-->
<script src="http://localhost:3000?callback=show"></script>
服务器端:
const http = require("http");
const url = require("url");
http.createServer(
(req,res)=>{
var Url = url.parse(req.url,true);
//接收客户端传过来的名为callback的参数中保存的函数名
var callback = Url.query.callback;
var weather="北京 晴";
//将函数名动态拼接到要返回的函数调用语句中。
res.write(`${callback}("${weather}")`);//实际想要在客户端执行的函数调用语句。
res.end();
}
).listen(3000);
script只能识别js语句,一旦接收到js语句就立即执行。于是在服务器端拼接一条函数调用的js语句,并且提前在客户端定义一个函数,当客户端接收到服务器返回的js语句后就会立即执行。
为了使函数名在客户端可修改,于是用请求参数将函数名从客户端传递给服务器。
动态创建script元素
script是在页面中写死的,只能在页面加载过程中执行一次,如果想每次单击按钮,随时发送请求,可以每次单击按钮时动态创建script元素。
<body>
<button>发送请求</button>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<script>
function show(weather){
alert(weather);
$("body>script:last").remove();//删除创建的那个script元素
}
//show('返回的数据');
$("button").click(function(){
var script = document.createElement('script');
script.src="http://localhost:3000?callback=show";
document.body.appendChild(script);
})
</script>
</body>
jQuery对jsonp方式跨域进行了终极简化
1.服务端代码不变,js代码如下:
最简单的方式,只需配置一个dataType:‘jsonp’,就可以发起一个跨域请求。
jsonp指定服务器返回的数据类型为jsonp格式,可以看发起的请求路径,自动带了一个callback=xxx,xxx是jquery随机生成的一个回调函数名称。//callback: jQuery34105977893922582984_1578207815633
_: 1578207815634
这里的success就跟上面的show一样,如果有success函数则默认success()作为回调函数。
<body>
<button>发送请求</button>
<script src="jquery.js"></script>
<script>
$("button").click(function(){
$.ajax({
url: "http://localhost:3000",
type: "GET",
dataType: "jsonp", //其实也是动态创建script,借助script发送跨域请求,必须有服务端的支持,
success: function(weather) {
alert(weather);
}
})
})
</script>
</body>
2.再看下如何指定特定的回调函数:
jsonpCallback: “show”,
看请求参数 callback: show_: 1578208620937,请求时带的参数是:callback=show;调用回调函数的时候,先调用了指定的show,然后再调用了success。所以,success是返回成功后必定会调用的函数,就看你怎么写了。
<script>
function show(weather) {
alert("show"+weather);
}
$("button").click(function(){
$.ajax({
url: "http://localhost:3000",
type: "GET",
dataType: "jsonp",
jsonpCallback: "show", //指定特定的回调函数
success: function(weather) {
alert(weather);
}
})
})
</script>
3.再看看如何改变callback这个名称:
jsonp: “func”,
看请求信息:func: show_: 1578208954673
<script>
function show(weather) {
alert("show"+weather);
}
$("button").click(function(){
$.ajax({
url: "http://localhost:3000",
type: "GET",
dataType: "jsonp",
jsonp: "func", //改变callback这个名称
jsonpCallback: "show",
success: function(weather) {
alert(weather);
}
})
})
</script>
指定callback这个名称后,后台也需要跟着更改。
http.createServer(
//每当有客户端发来请求时,自动调用一下回调函数。
(req,res)=>{
var Url = url.parse(req.url,true);
//接收客户端传过来的名为callback的参数中保存的函数名
var callback = Url.query.func;
var weather="北京 晴";
//将函数名动态拼接到要返回的函数调用语句中。
res.write(`${callback}("${weather}")`);//实际想要在客户端执行的函数调用语句。
res.end();
}
).listen(3000);
总结
jsonp的实现方式其实也是动态创建script,借助script发送跨域请求,jquery中ajax的jsonp对这个复杂的过程进行了封装,并且需要服务端的支持,所以可想而知,jsonp是不支持POST方式的。
jsonp的原理:
动态创建script标签,并且自动给script的src属性加入了callback参数,借助script来发送跨域请求,请求结束后script会被自动删除。并且必须有服务器端配合接收callback保存的函数名,服务端将要返回的数据填充到函数调用语句里返回,客户端收到js语句执行。