注册

jsonp的原理是什么?它是怎么实现跨域的?



写在前面

一说到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>

运行结果

202112122320721.webp

以上证明,我们完全可以在服务器端生成一段脚本,然后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'})";
?>

运行结果

202112122321351.webp

是的,我们发现完全没问题,我们平常调用接口就是要的后端返回的数据,上面的例子,后端生成脚本时已然给我们传递了参数,拿到数据之后,我们可以做任何我们想做的事。

问题:如果后端接口这么写,那么前端所有调用这个接口的地方,岂不是都要定义一个 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'})";
?>

运行结果

202112122319972.webp

说到这儿,我好像还是没说原理是啥,其实你看完上面的也就理解了

jsonp实际上就是

  • 1、前端调用后端时传递给后端数据的处理函数callback

  • 2、后端收到处理函数callback之后,进行数据库查询等操作,将后端要传递给前端的数据(一般为json格式)放入callback函数的()中并返回【实际上就是由后端动态生成一个前端可用的js脚本】,

  • 3、html页面在脚本文件加载后,自动执行脚本

  • 4、完成了整个jsonp请求。

优缺点

优点:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都 可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。

缺点:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行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);
}


作者:小枫学幽默
来源:https://juejin.cn/post/7040730836156547086

0 个评论

要回复文章请先登录注册