深入浅出jsonp(转)

前言

  第一次听说jsonp,其实早在2年之前。当时在做一个活动页面的抽奖模块,要从服务端get一个概率,当时什么都不懂,同事说用ajax,我就用ajax,同事说dataType改成jsonp,我就改成jsonp。于是乎活动页面做完了,以后也没有碰到过jsonp,在这期间我一直以为jsonp跟ajax息息相关,是xhr的一种特殊的跨域形式...直到一个月前的一次面试,问到jsonp我被虐成狗,才决定看下jsonp,好吧,原来jsonp也不是很难。

为什么要用jsonp?

  相信大家对跨域一定不陌生,对同源策略也同样熟悉。什么,你没听过?没关系,既然是深入浅出,那就从头说起。

  假如我写了个index页面,页面里有个请求,请求的是一个json数据(不知道json数据的猛戳JSON简介以及用法汇总),简单思考写下如下代码:

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

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

  楼主把两个文件都放在wamp下的www文件夹下,ajax请求没有跨域,完美得到结果:

  但是如果我的json文件和index文件不在一个域下,即跨域(不懂跨域的可参考JavaScript 的同源策略)了呢?

  试着在wamp下新开个apache端口(不知道怎么开的可参考WampServer下使用多端口访问),将json文件放到该服务端口的文件夹下(楼主设置的端口号为8080,默认的是80端口),试着发送请求:

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

  很显然,提示跨域了!怎么搞?这时jsonp就要出马了!

神奇的script标签

  与jsonp息息相关的是script标签,而xhr或者说传统意义上的ajax与之没有半毛钱关系!

  接着看上面的index.html代码,我们看到页面引用了百度cdn的jquery路径,对于这样的方式我们似乎已经习以为常,但是仔细一想,script标签可是完完全全的跨域的啊...没错,jsonp的实现核心就是利用script标签的跨域能力!于是我们灵机一动,似乎可以这么搞,动态生成一个script标签,把json的url赋值给script的src属性,然后再把这个script标签插入dom里...

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

  我们创建了一个script标签,而标签内包裹的内容正是需要的json数据,但是报错如下:

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

<body>
  <script src=‘http://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://localhost:8080/a.json‘;
    document.body.appendChild(s);
  </script>
</body>

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

  当然,这时的a.json文件并不一定要这样命名,改成a.js也不会有一点问题。

  而如果是与服务端交互也是一样的道理,比如和php:

<body>
  <script src=‘http://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://localhost:8080/test.php?callback=jsonpcallback";
    document.body.appendChild(s);
  </script>
</body>

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

  需要注意的是,jsonp提供的url(即动态生成的script标签的src),无论看上去是什么形式,最终生成返回的都是一段js代码。

JQuery对jsonp的封装

  为了便于开发,jq对jsonp也进行了封装,封装在了ajax方法中。

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

CallBack({
  "name": "hanzichi",
  "age": 10
});

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

<script src=‘http://libs.baidu.com/jquery/2.0.0/jquery.min.js‘></script>
<script type="text/javascript">
  $.ajax({
    url: ‘http://localhost:8080/test.php‘,
    dataType: ‘jsonp‘,
    success: function (data) {
      console.log(data);
    }
  });
</script>

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

当然类似的封装好的方法还有几种:

// 1
$.getJSON("http://localhost:8080/test.php?callback=?", function(data) {
  console.log(data);
});

// 2
$.get(‘http://localhost:8080/test.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 那个处理函数,所以一般不用特意处理。二如果要写死callback名的话,可以参照上文。

总结

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

  jsonp原理:

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

http://www.cnblogs.com/zichi/p/4593047.html

时间: 2024-10-07 05:06:31

深入浅出jsonp(转)的相关文章

深入浅出jsonp

前言 第一次听说jsonp,其实早在2年之前.当时在做一个活动页面的抽奖模块,要从服务端get一个概率,当时什么都不懂,同事说用ajax,我就用ajax,同事说dataType改成jsonp,我就改成jsonp.于是乎活动页面做完了,以后也没有碰到过jsonp,在这期间我一直以为jsonp跟ajax息息相关,是xhr的一种特殊的跨域形式...直到一个月前的一次面试,问到jsonp我被虐成狗,才决定看下jsonp,好吧,原来jsonp也不是很难. 为什么要用jsonp? 相信大家对跨域一定不陌生,

深入浅出JSONP:解决AJAX跨域问题

本文主要讲解了如何去解决AJAX跨域的问题,从跨域的简单原理到JONP实现模式详细的讲解整个解决方案,最后利用jQuery可以很方便的实现JSONP来进行跨域访问. 上周客户新买了服务器,原本在旧的服务器上放着客户的Web主页信息和一个后台程序(asp.net),在客户的主页中有一个动态显示最新消息的处理,这个处理就是通过ajax异步从那个后台程序中取得的.由于又购买了新的服务器,客户想把web主页和那个后台程序分开来,后台程序被部署到了新的服务器上.不过这个项目是我的同事小福同志开发的,也就由

同源策略和跨域问题

1 同源策略 所谓同源策略,指的是浏览器对不同源的脚本或者文本的访问方式进行的限制.比如源a的js不能读取或设置引入的源b的元素属性. 那么先定义下什么是同源,所谓同源,就是指两个页面具有相同的协议,主机(也常说域名),端口,三个要素缺一不可. 可以看下面的几个示例来更加清楚的了解一下同源的概念: URL1 URL2 说明 是否允许通信 http://www.foo.com/js/a.js http://www.foo.com/js/b.js 协议.域名.端口都相同 允许 http://www.

也谈谈同源策略和跨域问题

1 同源策略 所谓同源策略,指的是浏览器对不同源的脚本或者文本的访问方式进行的限制.比如源a的js不能读取或设置引入的源b的元素属性. 那么先定义下什么是同源,所谓同源,就是指两个页面具有相同的协议,主机(也常说域名),端口,三个要素缺一不可. 可以看下面的几个示例来更加清楚的了解一下同源的概念: URL1 URL2 说明 是否允许通信 http://www.foo.com/js/a.js http://www.foo.com/js/b.js 协议.域名.端口都相同 允许 http://www.

深入浅出:了解jsonp跨域的九种方式

什么是“”跨域”: 跨域访问,简单来说就是 A 网站的 javascript 代码试图访问 B 网站,包括提交内容和获取内容.由于安全原因,跨域访问是被各大浏览器所默认禁止的.当一个域与其他域建立了信任关系后,2个域之间不但可以按需要相互进行管理,还可以跨网分配文件和打印机等设备资源,使不同的域之间实现网络资源的共享与管理.这就形成了“跨域”. 广义的跨域: 1.) 资源跳转: A链接.重定向.表单提交2.) 资源嵌入: <link>.<script>.<img>.&l

深入浅出JSONP--解决ajax跨域问题

Jsonp跨域请求 2015-01-31 11:25 [转载]深入浅出JSONP--解决ajax跨域问题 ?JSONP和JSON好像啊,他们之间有什么联系吗? JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.对于JSON大家应该是很了解了吧,不是很清楚的朋友可以去json.org上了解下,简单易懂. JSONP是JSON with Padding的略称.它是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascri

# 深入浅出爬虫之道: Python、Golang与GraphQuery的对比

深入浅出爬虫之道: Python.Golang与GraphQuery的对比 本文将分别使用 Python ,Golang 以及 GraphQuery 来解析某网站的 素材详情页面 ,这个页面的特色是具有清晰的数据结构,但是DOM结构不够规范,无法通过单独的选择器定位页面元素,对页面的解析造成了一些曲折.通过这个页面的解析过程,深入浅出的了解爬虫的解析思想与这些语言之间的异同. 深入浅出爬虫之道: Python.Golang与GraphQuery的对比 一.前言 1. 语义化的DOM结构 2. 稳

下载-深入浅出Netty源码剖析、Netty实战高性能分布式RPC、NIO+Netty5各种RPC架构实战演练三部曲视频教程

下载-深入浅出Netty源码剖析.Netty实战高性能分布式RPC.NIO+Netty5各种RPC架构实战演练三部曲视频教程 第一部分:入浅出Netty源码剖析 第二部分:Netty实战高性能分布式RPC 第三部分:NIO+Netty5各种RPC架构实战演练

原生jsonp跨域

<script> // jsonp跨域原生写法 var script = document.createElement('script'); script.src = 'http://192.168.7.16/kuayu/test02.php?callback=aa'; document.body.appendChild(script); //aa('后台数据') function aa(res) { alert(res.website); } </script>