前端学习程序员我是程序员;您好程先生;叫我序员就好了

jsonp跨域实践(附其他实现跨域的方法)

2016-02-29  本文已影响664人  webCoder

面试中常常会问到如何使用jsonp跨域(jsonp跨域的原理是什么),这篇文章就给大家介绍一下相关的知识,如有不对,麻烦指出 ~

1. 首先我们比较一下json和jsonp
2.为什么会出现jsonp
1)、一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题,甭管你是静态页面、动态网页、web服务、WCF,只要是跨域请求,一律不准。
2)、不过我们又发现,Web页面上调用js文件时则不受是否跨域的影响(不仅如此,我们还发现凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>、<img>、<iframe>)。
3)、于是可以判断,当前阶段如果想通过纯web端(ActiveX控件、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据就只有一种可能,那就是在远程服务器上设法把数据装进js格式的文件里,供客户端调用和进一步处理。
4)、恰巧我们已经知道有一种叫做JSON的纯字符数据格式可以简洁的描述复杂数据,更妙的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据。
5)、这样子解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器上动态生成的js格式文件(一般以JSON为后缀),显而易见,服务器之所以要动态生成JSON文件,目的就在于把客户端需要的数据装入进去。
6)、客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己需求进行处理和展现了,这种获取远程数据的方式看起来非常像AJAX,但其实并不一样。
7)、为了便于客户端使用数据,逐渐形成了一种非正式传输协议,人们把它称作JSONP,该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

3.jsonp实现例子

alert("hello world");

我们本地localhost.com上有一个页面,里面引入了上面的js文件,当我们在浏览器中打开此页面时,会发现可以成功的弹出hello world,这就表示跨域调用成功了。

<html>
  <head> 
    <title></title> 
    <script type="text/javascript"> 
      var localHandler = function(data){ 
          alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result); 
      };                  
    </script> 
    <script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
    </head>
<body>
</body>
</html>

remoteserver.com上的remote.js文件内容:

localHandler({"result":"hello world"});

我们在浏览器中打开此页面localhost.html,发现弹出了

我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:hello world
跨域远程获取数据的目的基本实现了,但是又一个问题出现了,我怎么让远程js知道它应该调用的本地函数叫什么名字呢?毕竟是jsonp的服务者都要面对很多服务对象,而这些服务对象各自的本地函数都不相同啊?

<br >

思路:只要服务端提供的js脚本是动态生成的,这样调用者可以传一个参数过去告诉服务端 "我想要一段调用XXX函数的js代码,请你返回给我",于是服务器就可以按照客户端的需求来生成js脚本并响应了。

再看 localhost.html

<html>
  <head> 
    <title></title> 
    <script type="text/javascript"> 
       // 得到航班信息查询结果后的回调函数 
      var flightHandler = function(data){ 
          alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。'); 
      };
       // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码) 
      var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler"; 
      // 创建script标签,设置其属性 
      var script = document.createElement('script'); 
      script.setAttribute('src', url); 
      // 把script标签加入head,此时调用开始
      document.getElementsByTagName('head')[0].appendChild(script); 
    </script> 
    <script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
    </head>
<body>
</body>
</html>

我们看到调用的url中传递了一个code参数,告诉服务器我要查的是CA1998次航班的信息,而callback参数则告诉服务器,我的本地回调函数叫做flightHandler,所以请把查询结果传入这个函数中进行调用。
flightResult.aspx中:

{
  "code": "CA1998", 
  "price": 1780,
   "tickets": 5
}
<html>
 <head>
     <title>Untitled Page</title>
      <script type="text/javascript" src=jquery.min.js"></script>
      <script type="text/javascript">
        // 得到航班信息查询结果后的回调函数  
        var flightHandler = function(data){ alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。'); };

        jQuery(document).ready(function(){
          $.ajax({
             type: "get",
             async: false,
             url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998",
             dataType: "jsonp",
             jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
             jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
             success: function(json){
                 alert('您查询到航班信息:票价: ' + json.price + ' 元,余票: ' + json.tickets + ' 张。');
             },
             error: function(){
                 alert('fail');
             }
           });
         });
     </script>
 </head>
 <body>
 </body>
</html>

jquery帮你生成回调函数并把数据取出来供success属性方法来调用。

附其他实现跨域的方法:

参考文章:说说JSON和JSONP,也许你会豁然开朗,含jQuery用例

上一篇下一篇

猜你喜欢

热点阅读