js跨域之jsonp原理

作者: 小枫学幽默 | 来源:发表于2017-07-20 11:21 被阅读99次

    写在前面

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

    相关文章

      网友评论

        本文标题:js跨域之jsonp原理

        本文链接:https://www.haomeiwen.com/subject/xcrdkxtx.html