js跨域之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>

运行结果

image.png

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

运行结果

image.png

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

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

运行结果

image.png

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

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>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • JavaScript是一种在Web开发中经常使用的前端动态脚本技术。在JavaScript中,有一个很重要的...
    西瓜w阅读 1,813评论 0 1
  • AJAX 原生js操作ajax 1.创建XMLHttpRequest对象 var xhr = new XMLHtt...
    碧玉含香阅读 3,371评论 0 7
  • 1. 什么是同源策略 同源是指域名、协议、端口相同。同源策略(Same-Origin Policy)是浏览器的一个...
    65_刘璐阅读 728评论 0 0
  • Asynchronous JavaScript and XML (Ajax) 是驱动新一代 Web 站点(流行术语...
    张玉帅阅读 1,016评论 0 3
  • “璞玉”在生活中随处可见,发现它不难,需要我们对生活满怀足够热忱和期待,需要有清澈瞳仁随时随地去发现,现在许多人对...
    木果亲子乐园阅读 152评论 0 0