Jsonp 关键字详解及json和jsonp的区别,ajax和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 函数里.(动态执行回调函数)

 json和jsonp的区别,ajax和jsonp的区别

json和jsonp虽然只有一个字母的区别,但是它们之间扯不上关系。

json是一种轻量级的数据交换格式。

jsonp是一种跨域数据交互协议。

json的优点:(1)基于纯文本传递极其简单,(2)轻量级数据格式适合互联网传递,(3)容易编写和解析。

ajax和jsonp的区别:

相同点:都是请求一个url

不同点:ajax的核心是通过xmlHttpRequest获取内容

    jsonp的核心则是动态添加<script>标签来调用服务器 提供的js脚本。

(0)

相关推荐

  • Node.js返回JSONP详解

    在使用JQuery的Ajax从服务器请求数据或者向服务器发送数据时常常会遇到跨域无法请求的错误,常用的解决办法就是在Ajax中使用JSONP.基于安全性考虑,浏览器会存在同源策略,然而<script/>标签却具有跨域访问数据的能力,这就是JSONP工作的基本原理.有关同源策略以及什么是JSONP. 在Node.js中实现JSONP非常简单,通过下面的代码我们从服务器返回并运行一个JavaScript函数,这个JavaScript函数已经在调用方提前被定义好了,于是当它被返回的时候就自动执行了.

  • json与jsonp知识小结(推荐)

    json 1. json 的值可以是下面这些类型: ① 数字(整数或浮点数),比如123,1.23 ② 字符串(在双引号中) ③ 逻辑值(true 或 false) ④ 数组(在方括号中) ⑤ 对象(在花括号中) ⑥ null 2. json解析方法 ① eval('(' + jsondata + ')' ); 使用时永远是不安全的,代码注入 ② JSON.parse(jsondata); JSONLint json:字符串校验工具 3. jQuery 实现ajax jQuery.ajax([s

  • 浅析JSONP解决Ajax跨域访问问题的思路详解

    前几天,工作上有一新需求,需要前端web页面异步调用后台的Webservice方法返回信息.实现方法有多种,本例采用jQuery+Ajax,完成后,在本地调试了一切ok,但是部署到服务器上以后就出现问题了,后台服务调用没有响应,怎么回事?代码没怎么改动,唯一修改的地方就是jQuery的ajax方法中的url地址.难道是这里的问题,经过检查和调试,发现原来是同源策略在作怪,我们知道,JavaScript或jQuery是在Web前端开发中经常使用的动态脚本技术.在JavaScript中,有一个很重要

  • 浅谈JQuery+ajax+jsonp 跨域访问

    Jsonp(JSON with Padding)是资料格式 json 的一种"使用模式",可以让网页从别的网域获取资料. 一. 客户端 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv=&q

  • JSONP跨域请求实例详解

    JSOP简介 JSONP(JSON with Padding)是JSON的一种"使用模式",可用于解决主流浏览器的跨域数据访问的问题.由于同源策略,一般来说位于 server1.example.com 的网页无法与不是 server1.example.com的服务器沟通,而 HTML 的<script> 元素是一个例外.利用 <script> 元素的这个开放策略,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP.用 JSON

  • 浅析json与jsonp区别及通过ajax获得json数据后格式的转换

    有关json与jsonp的区别(json才是目的,jsonp只是手段)介绍如下所示: 一言以蔽之,json返回的是一串数据:而jsonp返回的是脚本代码(包含一个函数调用): JSON其实就是JavaScript中的一个对象,跟var obj={}在质上完全一样,只是在量上可以无限扩展.简单地讲,json其实就是JavaScript中的对象(Object)和数组(Array,其实也是对象)这倆好基友在那儿你嵌我我嵌你地套上n多层,以此模拟出许多复杂的数据结构. json易于人阅读和编写,也易于机

  • 跨域请求的完美解决方法(JSONP, CORS)

    一个众所周知的问题,Ajax直接请求普通文件存在跨域无权限访问的问题.解决方法有JSONP,Flash等等. JSONP 我们发现,Web页面上调用js文件时不受是否跨域的影响,凡是拥有"src"这个属性的标签都拥有跨域的能力,比如<script>.<img>.<iframe>.那就是说如果要跨域访问数据,就服务端只能把数据放在js格式的文件里.恰巧我们知道JSON可以简洁的描述复杂数据,而且JSON还被js原生支持,所以在客户端几乎可以随心所欲的处

  • 关于JSON与JSONP简单总结

    一.什么是json JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式. 易于人阅读和编写.同时也易于机器解析和生成. 它基于JavaScript Programming Language, Standard ECMA-262 3rd Edition - December 1999的一个子集. JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python

  • AJAX实现跨域的三种方法(代理,JSONP,XHR2)

    域: 域是WIN2K网络系统的安全性边界.我们知道一个计算机网最基本的单元就是"域",这一点不是WIN2K所独有的,但活动目录可以贯穿一个或多个域.在独立的计算机上,域即指计算机本身,一个域可以分布在多个物理位置上,同时一个物理位置又可以划分不同网段为不同的域,每个域都有自己的安全策略以及它与其他域的信任关系.当多个域通过信任关系连接起来之后,活动目录可以被多个信任域域共享. 由于在工作中需要使用AJAX请求其他域名下的请求,但是会出现拒绝访问的情况,这是因为基于安全的考虑,AJAX只

  • Jsonp 关键字详解及json和jsonp的区别,ajax和jsonp的区别

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

  • swift guard关键字详解及使用

    swift guard关键字详解及使用 Swift提供guard关键字,guard关键字可以简化繁琐的判断逻辑 func buy( money: Int , price: Int , capacity: Int , volume: Int){ if money >= price{ if capacity >= volume{ print("I can buy it!") print("\(money-price) Yuan left.") print(&

  • Java中final关键字详解

    谈到final关键字,想必很多人都不陌生,在使用匿名内部类的时候可能会经常用到final关键字.另外,Java中的String类就是一个final类,那么今天我们就来了解final这个关键字的用法. 主要介绍:一.final关键字的基本用法.二.深入理解final关键字 一.final关键字的基本用法 在Java中,final关键字可以用来修饰类.方法和变量(包括成员变量和局部变量).下面就从这三个方面来了解一下final关键字的基本用法. 1.修饰类 当用final修饰一个类时,表明这个类不能

  • C/C++ 中extern关键字详解

    C/C++ 中extern关键字详解 在C/C++编程过程中,经常会进行变量和函数的声明和定义,各个模块间共用同一个全局变量时,此时extern就派上用场了. 定义 extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义,不需要分配内存,直接使用. 推荐:在.h中声明,因为在头文件定义的话,其他模块include此头文件,就会报重复定义错误 实验结论 1.在.h中声明 extern int g_a; 在.c中定义 int g_

  • Java中Volatile关键字详解及代码示例

    一.基本概念 先补充一下概念:Java内存模型中的可见性.原子性和有序性. 可见性: 可见性是一种复杂的属性,因为可见性中的错误总是会违背我们的直觉.通常,我们无法确保执行读操作的线程能适时地看到其他线程写入的值,有时甚至是根本不可能的事情.为了确保多个线程之间对内存写入操作的可见性,必须使用同步机制. 可见性,是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的.也就是一个线程修改的结果.另一个线程马上就能看到.比如:用volatile修饰的变量,就会具有可见性.volatile修饰的

  • this关键字详解

    Java提供了一个this关键字,this关键字总是指向调用该方法的对象.根据this出现的位置的不同,this作为对象的默认引用有两种情形. 1)构造器中引用该构造器正在初始化的对象. 2)在方法中引用调用该方法的对象. this关键字最大的作用就是让类中一个方法,访问该类里的另一个方法或者实例变量.假设定义了一个Person类,这个Person对象的eat()方法需要调用它的move()方法,则如何做呢?是否应该定义如下的Person类呢? public class Person { //定

  • Java中final关键字详解及实例

    final在Java中可以声明成员变量.方法.类以及本地变量.一旦你将引用声明作final,你将不能改变这个引用了,如果你试图将变量再次初始化的话,编译器会报编译错误.  final的含义在不同的场景下有细微的差别,但总体来说,它指的是"不可变". 1. final变量 凡是对成员变量或者本地变量(在方法中的或者代码块中的变量称为本地变量)声明为final的都叫作final变量.final变量经常和static关键字一起使用,作为常量.用final关键字修饰的变量,只能进行一次赋值操作

  • Java关键字详解之final static this super的用法

    目录 1. final 关键字: 2. static 关键字: 3. this 关键字: 4. super 关键字: final,static,this,super 关键字总结 正文开始@Assassin 1. final 关键字: final 关键字,意思是最终的.不可改变的,初始化之后就不能再次修改 ,用来修饰类.方法和变量,具有以下特点: final 修饰的类不能被继承,final类中的所有成员方法都会被隐式的指定为 final 方法: final 修饰的方法不能被重写: final 修饰

  • c++中的volatile和variant关键字详解

    目录 一.两个长得有点像的变量 二.二者的功能 三.应用实例 四.总结 一.两个长得有点像的变量 对volatile关键字,其实很多人只是能用,知道用到啥处,但其实应用的原理并不知道.在一些多线程的通信中,往往是这个关键字应用到的场所,很多人也是如此想的.但其实这个想法是不准确的.volatile这个关键字的目的最初是针对硬件IO操作的,防止访问IO操作中的缓存影响到真实的数据.但这个关键字的溢出效应是,多线程也可以应用这个原理(注意在多核和多CPU编程中有危险,但是在其它语言如Java中,得按

  • Java中super和this关键字详解

    目录 父类空间优先于子类对象产生 super和this的含义 super和this的用法 继承的特点 父类空间优先于子类对象产生 在每次创建子类对象时,先初始化父类空间,再创建其子类对象本身.目的在于子类对象中包含了其对应的父类空间,便可以包含其父类的成员,如果父类成员非private修饰,则子类可以随意使用父类成员.代码体现在子类的构造方法调用时,一定先调用父类的构造方法. 理解图解如下:  super和this的含义 super :代表父类的存储空间标识(可以理解为父亲的引用). this

随机推荐