跨域:JSONP

这几天在看面试题,发现跨域这个知识点被问到很多次,网上搜了搜各种资料,五花八门,- - …整了半天,算是明白了什么意思。总结如下:

首先要明白的是:<script>标签是不受同源策略的限制的,它可以载入任意地方的 JavaScript 文件,而并不要求同源。同样的有src属性的标签都不受同源策略的限制,比如<img><iframe>.跨域的核心就是利用这个。

JSONP 的理念就是,我和服务端约定好一个函数名,当我请求文件的时候,服务端返回一段 JavaScript。这段 JavaScript 调用了我们约定好的函数,并且将数据当做参数传入.

先看个简单的:
需要获取数据的页面:index.html

<script>
    function getWeather(data) {
        console.log(data);
    }
</script>

<script src="http://x.y.com/xx.js">

http://x.y.com/xx.js 文件内容:

getWeather({
    "城市": "北京",
    "天气": "大雾"
});

我们可以看到,在我们定义了 getWeather(data) 这个函数后,直接载入了 xx.js。在这个脚本中,执行了 getWeather 函数,并传入了一个对象,并将这个对象输出到 console 中。
这就是整个 JSONP 的流程。

以上过程没有涉及到跟服务器的交互,下面看一下这个代码。

<script src="http://jd.com/data.php?callback=dosomething"></script>

<script type="text/javascript">
    function  dosomething(jsondata){
    console.log(jsondata);//打印获得的json数据
     }
</script>

按我自己的理解,第一个<script> 是载入http://jd.com/data.php,并且向data.php传入了一个回调函数名,也就是something,

data.php

<?php
$callback = $_GET['callback'];//得到回调函数名,
$data = {'name':'张三',sex:'男',age:'15'};//要返回的数据
echo$callback.'('.json_encode($data).')';//输出
?>

上面的data.php运行执行完毕后,输出dosomething({‘name’:’张三’,sex:’男’,age:’15’});,仔细看看这是什么。这不就是执行函数dosomething,参数是{‘name’:’张三’,sex:’男’,age:’15’},
函数执行完毕后,最后的输出结果是:
这里写图片描述

第二个与服务器交互的JSONP和第一个不与服务器交互的JSONP其实是一样的道理,只不过是第一个JSONP中第二个载入的<script> 已经写好了要执行的函数,并且指定了参数。第二个JSONP的第二个<script> 需要在后台拼接好带参执行函数的样子,然后执行。这时候,后台人员有必要知道前台要执行的函数的名字和参数。所以第二个JSONP的第一个<script> 声明了函数。

以上是原生函数的jsonp跨域过程。

看下用jQuery怎么写:

 <script type="text/javascript" src=jquery.min.js"></script>
      <script type="text/javascript">
     jQuery(document).ready(function(){
        $.ajax({
             type: "get",
             async: false,
             url: "http://jd.com/data.php",
             dataType: "jsonp",
             jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
             jsonpCallback:"dosomething",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
                 success: function {
            console.log(jsondata);//打印获得的json数据
             };
                     },
                 error: function(){
                     alert('fail');
                 }
         });
     });
     </script>

还有些别的封装方法:

$.getJSON("http://jd.com/data.php?callback=?", function(data) {  
  console.log(data);
});

// 2
$.get('http://jd.com/data.php', function(data) {  
  console.log(data);
}, 'jsonp');  

需要注意的是getJSON方法的请求地址url需要带上callback=?,因为jq对该方法进行封装的时候并没有默认回调函数变量名为callback,于是php中$_GET[‘callback’]就找不到变量值了。
而一般的jq方法url 中不用指定 callback 参数。对于 jQuery 中的 jsonp 来说,callback 参数是自动添加的。默认情况下,jQuery 生成的 jsonp 请求中 callback 参数是形如 callback=jQuery200023559735575690866_1434954892929 这种根据看似随机的名字,对应的就是 success 那个处理函数,所以一般不用特意处理。

最后来总结下JSONP的跨域:
关键点:浏览器对XHR做了同源策略,但并没有将这种方式延续到script上,从而可以利用动态script标签技术来做到跨域请求的作用。
兼容性:所有浏览器都兼容这种方式;
优点:很明显前端可以很轻松的做到跨域请求;
缺点
只能通过GET方式请求,一方面是参数长度有限制,二是安全性比较差;
**后端需要知道前端的回调函数是什么样的结构,主要在参数和回调名;
后端需要进行参数和回调函数名的拼接然后才能执行;**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值