jsonp学习汇总

为什么要使用jsonp?
为了解决在不同域名下,即跨域(参考JavaScript同源策略)获取数据的问题。

这是同域请求

<script src='//libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
<script type="text/javascript">
    $.ajax({
        url: 'http://127.0.0.1/a.json',
        dataType: "json",
        success: function (data) {
            console.log(data);
        }
    });
</script>

a.json

{
    "name": "sun",
    "age": 10
}

2015-07-11_143704

如果换成跨域?

<script src='//libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
<script type="text/javascript">
    $.ajax({
        url: 'http://www.sun.cn/a.json',
        dataType: "json",
        success: function (data) {
            console.log(data);
        }
    });
</script>

2015-07-11_144552
提示跨域了,现在就需要jsonp出马。

仔细看在页面中,用了百度CND的jq路径,这在平常已经习以为常,有木有发现,script标签可以跨域!于是想在这里下手,似乎可以弄个动态生成的script标签,把json的值写到script的src属性里面,然后在把这script写到dom里面。试下

<script src='//libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
<script type="text/javascript">
    var s = document.createElement('script');
    s.src = 'http://www.sun.cn/a.json';
    document.body.appendChild(s);
</script>

2015-07-11_145945
原因是因为json数据并不是合法的js语句,把上面的json数据放在一个回调函数中有一个最简单的方法:

<script src='//libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
<script type="text/javascript">
    function jsonpcallback(json) {
        console.log(json);
    }

    var s = document.createElement('script');
    s.src = 'http://www.sun.cn/b.json';
    document.body.appendChild(s);
</script>

b.json

jsonpcallback({
    "name": "sun",
    "age": 10
});

2015-07-11_150929

Jquery对jsonp封装

<script src='//libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
<script type="text/javascript">
   $.ajax({
        url: 'http://www.sun.cn/b.json',
        dataType: 'jsonp',
        jsonpCallback: 'jsonpcallback',
        success: function (data) {
            console.log(data);
        }
    });
</script>

截图与上一个例子相同,就不再截图。

以上代码是针对请求文件中写死了callback函数名的情况。因为请求的是json文件,json不是服务器端的动态语言不能进行解析,如果是jsp或者其他的服务器端语言,则不用写死函数名,比如下面这样:

<script src='//libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
<script type="text/javascript">
    $.ajax({
        url: 'http://www.sun.cn/jsonp.jsp',
        dataType: 'jsonp',
        success: function (data) {
            console.log(data);
        }
    });

jsonp.jsp

String callback = request.getParameter("callback");
out.print(callback+"([ { name:\"跨域访问成功!\"},{ name:\"跨域访问失败!\"}])");

2015-07-11_152659

还有两个简单写法

<script type="text/javascript">
    // 简单写法 1
    $.getJSON("http://www.sun.cn:81/jsonp.php?callback=?", function(data) {
        console.log(data);
    });

    // 简单写法 2
    $.get('http://www.sun.cn:81/jsonp.php', function(data) {
        console.log(data);
    }, 'jsonp');
</script>

jsonp.php

<?php
    $jsondata = '{
        "name": "sun.php",
        "age": 10
      }';
    echo $_GET['callback'].'('.$jsondata.')';
?>

2015-07-11_153459

总结
由于同源策略限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源,为了实现跨域请求,可以通过script标签实现跨域请求,然后在服务端输出JSON数据并执行回调函数,从而解决了跨域的数据请求,这就是jsonp的核心。

jsonp原理:

  1. 首先在客户端注册一个callback, 然后把callback的名字传给服务器。
  2. 服务器先生成 json 数据。 然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 jsonp. 最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。
  3. 客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里.(动态执行回调函数)

发表评论