zoukankan      html  css  js  c++  java
  • 跨域之jsonp

    我们都知道使用<script>标签可以引入外部的JS文件,即使这个JS文件来自于其他的网站,比如我们引用存放在网络服务器上的jQuery框架。在这个过程中,我们已经实现跨域访问。像<script>标签这种本身具有跨域访问能力的标签还有<link>、<img>、<iframe>等。jsonp的实现原理就是利用<script>标签,实现了跨域访问。

    先看一个例子:

    先创建一个html文件,代码如下:

    1 <body>
    2    <p>名字:<span id="name"></span></p>
    3 <script>
    4   function test(obj) {
    5    document.getElementById("name").innerHTML = obj.name;
    6   }
    7 </script>
    8 </body>

    此时在浏览器打开这个文件,页面中只有“名字:”这三个字符。

    现在创建一个JS文件,test.js,其中的代码如下:

    1 var person = {
    2     name: "Jack",
    3     age: 20
    4 }
    5 test(person);

    通过<script>标签在html文件中引入这个test.js文件(添加到body结束标签之前):

    1 <script src="test.js"></script>

    再在浏览器中打开html文件就会看到:

    如果把这个test.js放在百度的服务器上,在淘宝的页面上有一个test函数声明,然后动态地创建一个<script>标签来引用这个test.js,那么在淘宝的页面上就可以显示来自百度的服务器的数据,这就是jsonp的原理。当然引用的不一定非要是js文件,也可以是php、.net等文件,只要在这些文件中事先写好相应的代码即可。

    下面用聚合数据的天气预报接口和新浪的城市查询接口为例来介绍jsonp。

    首先是新浪的城市查询接口。

    新浪的城市查询接口是:

    http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js

    可以直接在浏览器中打开,发现是一个名为remote_ip_info的Javascript对象,

    var remote_ip_info = {
        "ret":1,
        "start":-1,
        "end":-1,
        "country":"u4e2du56fd",
        "province":"u6cb3u5357",
        "city":"u8bb8u660c",
        "district":"",
        "isp":"",
        "type":"",
        "desc":""
    };

    那么在本地的测试页面中可以使用这个接口获取所在的城市,代码如下:

     1 //获取当前城市
     2     function getCity(url) {
     3       var city = '';
     4       //创建一个script标签
     5       var script = document.createElement("script");
     6       //设置script标签引用的url
     7       script.setAttribute("src",url);
     8       //将script标签添加到头部,也可以添加到其他地方
     9       var head = document.getElementsByTagName('head')[0];
    10       head.appendChild(script);
    11       //如果script标签加载完成,获取城市
    12       script.onload = function() {//script.onload不兼容IE8及以下版本
    13          city = remote_ip_info["city"];
    14          console.log(city);
    15       };
    16 
    17       //移除创建的script标签
    18       head.removeChild(script);
    19     }
    20 
    21     //该URL是新浪的获取当前城市的API,采用jasop方法获取数据
    22     getCity("http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js");

    下面是聚合数据的天气预报接口。

    接口示例:http://op.juhe.cn/onebox/weather/query?cityname=%E6%B8%A9%E5%B7%9E&key=您申请的KEY

    使用这个接口时至少要传入三个参数:

    1. cityname是要查询的城市名,可以用前面新浪的城市查询接口得到的数据。
    2. key是申请使用聚合数据天气预报接口时,给的APPKey。
    3. 另外还有一个callback参数,传入一个函数名,服务器会把查询后得到的数据拼接成函数调用的形式返回来,比如传入test函数名,则返回来test({"date":"2011-11-11","wind":"微风"}),所以要在测试页面声明好这个函数,以便对返回来的数据进行处理。

    下面是代码:

    html代码,将获得数据在页面中显示出来

    1 <p id="chuanyi"></p>
    2 <p id="yundong"></p>
    3 <p id="ziwaixian"></p>

    获得天气情况数据的代码,原理与获取当前城市的原理一样,不同的是要事先指定回调函数,并将函数名加到url的末尾。

     1 function $(id) {
     2       return document.getElementById(id);
     3 }
     4 
     5 //指定回调函数
     6     function callback(data) {
     7      $("chuanyi").innerHTML = "穿衣指数:" + data.result.data.life.info.chuanyi;
     8      $("yundong").innerHTML = "运动指数:" + data.result.data.life.info.yundong;
     9      $("ziwaixian").innerHTML = "紫外线:" + data.result.data.life.info.ziwaixian;
    10     }
    11 
    12     function getWeather(city) {
    13       var url = 'http://op.juhe.cn/onebox/weather/query?cityname='+encodeURIComponent(city)+'&key=abbac0fc4fccbec34891de77bb1cfb4e&callback=callback';//该URL是聚合数据的天气预报API,采用jasop方法获取数据
    14       console.log(encodeURIComponent(city));
    15       var script = document.createElement("script");
    16       script.setAttribute("src",url);
    17       var head = document.getElementsByTagName('head')[0];
    18       head.appendChild(script);
    19       head.removeChild(script);
    20     } 

    有了以上代码,还不能获取到天气数据,因为getWeather()函数还没有调用。为了能将获取到的城市数据传给getWeather()函数,要在getCity()函数内部script的onload事件处理程序中调用getWeather()函数。

    下面是调用getWeather函数返回的数据,一大串:

      1 callback({
      2     "reason":"successed!",
      3     "result":{
      4         "data":{
      5             "pubdate":"2016-11-11",
      6             "pubtime":"11:00:00",
      7             "realtime":{
      8                 "city_code":"101180401",
      9                 "city_name":"许昌",
     10                 "date":"2016-11-11",
     11                 "time":"16:00:00",
     12                 "week":5,
     13                 "moon":"十月十二",
     14                 "dataUptime":1478853365,
     15                 "weather":{
     16                     "temperature":"15",
     17                     "humidity":"64",
     18                     "info":"多云",
     19                     "img":"1"
     20                 },
     21                 "wind":{
     22                     "direct":"南风",
     23                     "power":"3级",
     24                     "offset":null,
     25                     "windspeed":null
     26                 }
     27             },
     28             "life":{
     29                 "date":"2016-11-11",
     30                 "info":{
     31                     "chuanyi":["较冷","建议着厚外套加毛衣等服装。年老体弱者宜着大衣、呢外套加羊毛衫。"],
     32                     "ganmao":["较易发","天凉,昼夜温差较大,较易发生感冒,请适当增减衣服,体质较弱的朋友请注意适当防护。"],
     33                     "kongtiao":["较少开启","您将感到很舒适,一般不需要开启空调。"],
     34                     "xiche":["较适宜","较适宜洗车,未来一天无雨,风力较小,擦洗一新的汽车至少能保持一天。"],
     35                     "yundong":["较适宜","天气较好,但考虑气温较低,推荐您进行室内运动,若户外适当增减衣物并注意防晒。"],
     36                     "ziwaixian":["弱","紫外线强度较弱,建议出门前涂擦SPF在12-15之间、PA+的防晒护肤品。"]
     37                 }
     38             },
     39             "weather":[
     40                 {
     41                     "date":"2016-11-11",
     42                     "info":{
     43                         "day":["1","多云","17","","微风","06:53"],
     44                         "night":["0","晴","7","","微风","17:23"]
     45                     },
     46                     "week":"五",
     47                     "nongli":"十月十二"
     48                 },
     49                 {
     50                     "date":"2016-11-12",
     51                     "info":{
     52                         "dawn":["0","晴","7","无持续风向","微风","17:23"],
     53                         "day":["0","晴","17","","微风","06:54"],
     54                         "night":["1","多云","8","","微风","17:23"]
     55                     },
     56                     "week":"六",
     57                     "nongli":"十月十三"
     58                 },
     59                 {
     60                     "date":"2016-11-13",
     61                     "info":{
     62                         "dawn":["1","多云","8","无持续风向","微风","17:23"],
     63                         "day":["1","多云","17","","微风","06:55"],
     64                         "night":["0","晴","9","","微风","17:22"]
     65                     },
     66                     "week":"日",
     67                     "nongli":"十月十四"
     68                 },
     69                 {
     70                     "date":"2016-11-14",
     71                     "info":{
     72                         "dawn":["0","晴","9","无持续风向","微风","17:22"],
     73                         "day":["1","多云","17","","微风","06:56"],
     74                         "night":["2","阴","5","","微风","17:21"]
     75                     },
     76                     "week":"一",
     77                     "nongli":"十月十五"
     78                 },
     79                 {
     80                     "date":"2016-11-15",
     81                     "info":{
     82                         "dawn":["2","阴","5","无持续风向","微风","17:21"],
     83                         "day":["1","多云","13","","微风","06:57"],
     84                         "night":["1","多云","6","","微风","17:21"]
     85                     },
     86                     "week":"二",
     87                     "nongli":"十月十六"
     88                 }
     89             ],
     90             "f3h":{
     91                 "temperature":[
     92                     {
     93                         "jg":"20161111170000",
     94                         "jb":"15"
     95                     },
     96                     {
     97                         "jg":"20161111200000",
     98                         "jb":"13"
     99                     },
    100                     {
    101                         "jg":"20161111230000",
    102                         "jb":"10"
    103                     },
    104                     {
    105                         "jg":"20161112020000",
    106                         "jb":"10"
    107                     },
    108                     {
    109                         "jg":"20161112050000",
    110                         "jb":"8"
    111                     },
    112                     {
    113                         "jg":"20161112080000",
    114                         "jb":"7"
    115                     },
    116                     {
    117                         "jg":"20161112110000",
    118                         "jb":"14"
    119                     },
    120                     {
    121                         "jg":"20161112140000",
    122                         "jb":"16"
    123                     },
    124                     {
    125                         "jg":"20161112170000",
    126                         "jb":"14"
    127                     }
    128                 ],
    129                 "precipitation":[
    130                     {"jg":"20161111170000","jf":"0"},
    131                     {"jg":"20161111200000","jf":"0"},
    132                     {"jg":"20161111230000","jf":"0"},
    133                     {"jg":"20161112020000","jf":"0"},
    134                     {"jg":"20161112050000","jf":"0"},
    135                     {"jg":"20161112080000","jf":"0"},
    136                     {"jg":"20161112110000","jf":"0"},
    137                     {"jg":"20161112140000","jf":"0"},
    138                     {"jg":"20161112170000","jf":"0"}
    139                 ]
    140             },
    141             "pm25":{
    142                 "key":"Xuchang",
    143                 "show_desc":0,
    144                 "pm25":{
    145                     "curPm":"50",
    146                     "pm25":"25",
    147                     "pm10":"51",
    148                     "level":1,
    149                     "quality":"优",
    150                     "des":"可正常活动。"
    151                 },
    152                 "dateTime":"2016年11月11日16时",
    153                 "cityName":"许昌"
    154             },
    155             "jingqu":"",
    156             "jingqutq":"",
    157             "date":"",
    158             "isForeign":"0"
    159         }
    160     },
    161     "error_code":0
    162 })
    View Code

    这篇文章讲解的很详细:jsonp协议原理深度解析

    (完)

  • 相关阅读:
    HTTP 错误 500.19 配置文件错误 ( 0x8007000d,0x80070032)
    system.web下的HttpModules节点和system.webServer下的modules节点的配置区别
    索引超出了数组界限(Microsoft.SqlServer.Smo)
    VS 附加进程调试 Web项目
    VS 调试 无法启动IIS Express Web 服务器(进程不存在)
    java基础面试题
    给dubbo接口添加白名单——dubbo Filter的使用
    mysql行转列转换
    Spring透过ApplicationListener来触发contextrefreshedevent事件
    spring mvc之请求过程源码分析
  • 原文地址:https://www.cnblogs.com/fogwind/p/6058868.html
Copyright © 2011-2022 走看看