写在前面
一说到javascript的跨域,很多人第一时间想到的就是jsonp
(JSON with Padding),那么这种跨域方式的实现原理是什么?
我承认我使用了很长时间,但是还是现在才知道,原来是这样....
问题,如果我在 本地 访问 api.com下面的接口,会出现跨域请求的问题,为什么jsonp能解决这个?
- 1、script标签是用来加载什么的?
加载js脚本的,src写上一个脚本的地址,然后浏览器就能加载啊! - 2、那么本地
jsonp.html
的script标签可以加载api.com
的域名下面的脚本文件吗?
可以啊!要不那些用CDN方式优化网页加载速度的,是不可能成功的如
<script type="text/javascript" src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
- 3、那么script能加载别的域名下面的脚本文件,与
jsonp
何干?
我们都知道,加载api.com
的域名下面的js脚本是可以的,此时,api.com
下面的js脚本文件为真实存在的静态资源。那么如果这个脚本文件是由后端语言生成的呢?实例使用php
==>jsonp.php
<?php
echo 'alert("Hello world")';
?>
- 4、那么问题来了,我们生成js脚本的文件为.php文件啊,怎么加载这个脚本?
答案是:我们的script
标签是能够加载.php文件的,也就是
<script type="text/javascript" src='http://localhost/jsonp.php'></script>
运行结果
以上证明,我们完全可以在服务器端生成一段脚本,然后html页面用script标签去加载然后执行脚本。
那么,我们可以在生成的脚本中执行html中定义的方法吗?我们来试一下
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>jsonp</title>
</head>
<body>
</body>
<script type="text/javascript">
function execWithJsonp(para){
console.log('我被jsonp.php中的脚本执行了,传递过来的参数是==>'+para);
console.log(para)
}
</script>
<script type="text/javascript" src='http://localhost/jsonp.php'></script>
</html>
jsonp.php
<?php
echo "execWithJsonp({status:'ok'})";
?>
运行结果
是的,我们发现完全没问题,我们平常调用接口就是要的后端返回的数据,上面的例子,后端生成脚本时已然给我们传递了参数,拿到数据之后,我们可以做任何我们想做的事。
问题:如果后端接口这么写,那么前端所有调用这个接口的地方,岂不是都要定义一个
execWithJsonp
方法?
如果页面调用两次,处理逻辑还不一样,那么我们岂不是要区分是哪一次?我希望每次访问接口调用不同的处理数据函数,每次我来告诉后端用哪个函数来处理返回的数据。
当然可以,我们可以这么做
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>jsonp</title>
</head>
<body>
</body>
<script type="text/javascript">
function execWithJsonp(para){
console.log('我被jsonp.php中的脚本执行了,我是execWithJsonp,传递过来的参数是==>'+para);
console.log(para)
}
function doExecJsonp(para){
console.log('我被jsonp.php中的脚本执行了,我是doExecJsonp,传递过来的参数是==>'+para);
console.log(para)
}
</script>
<script type="text/javascript" src='http://localhost/jsonp.php?callback=doExecJsonp'></script>
<script type="text/javascript" src='http://localhost/jsonp.php?callback=execWithJsonp'></script>
</html>
jsonp.php
<?php
$callback=$_GET['callback'];
echo $callback."({status:'ok'})";
?>
运行结果
说到这儿,我好像还是没说原理是啥,其实你看完上面的也就理解了
jsonp实际上就是
- 1、前端调用后端时传递给后端数据的处理函数
callback
- 2、后端收到处理函数
callback
之后,进行数据库查询等操作,将后端要传递给前端的数据(一般为json格式)放入callback
函数的()
中并返回【实际上就是由后端动态生成一个前端可用的js脚本】, - 3、html页面在脚本文件加载后,自动执行脚本
- 4、完成了整个jsonp请求。
优缺点
优点:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都 可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。
缺点:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题,切很明显的需要后端工程师配合才能完成。
后记,发挥自己的想象吧,看这东西该怎么操作好
<script type="text/javascript">
function execWithJsonp(para){
console.log('我被jsonp.php中的脚本执行了,我是execWithJsonp,传递过来的参数是==>'+para);
console.log(para)
}
function doExecJsonp(para){
console.log('我被jsonp.php中的脚本执行了,我是doExecJsonp,传递过来的参数是==>'+para);
console.log(para)
}
doJsonp('doExecJsonp')
function doJsonp(callbackName){
var script=document.createElement('script');
script.src='http://localhost/jsonp.php?callback='+callbackName;
document.body.appendChild(script);
}
</script>