深入理解jsonp原理——前端面试

张三的美丽家园      2022-02-08     642

关键词:

JSON和JSONP虽然只有一个字之差,但是它们俩是八竿子打不着的:JSON是一种数据交换格式,JSONP是非正式的跨域数据交换协议。

为什么说JSONP是非正式的传输协议呢?因为它就是利用了<script>标签没有跨域限制这一“漏洞”来达到与第三方通讯的目的。简单地说,该协议就是,允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名包裹json数据,这样客户端就可以随意定制自己的函数自动处理返回的数据了。

即,需要通讯时,本站脚本创建一个<script>元素,地址指向第三方的API网址,形如:
<script src="http://www.example.net/api?param1=1&param2=2"></script>
并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。
第三方产生的响应为json数据的包装(故称之为jsonp,即json padding),形如:
callback({"name":"hax","gender":"Male"})
这样浏览器会调用callback函数,并传递解析后json对象作为参数。本站脚本可在callback函数里处理所传入的数据。

听完上面的简述你还是一脸懵逼,那下面就来详细说说到底什么是JSONP。
先说说JSONP是怎么产生的
1.众所周知,Ajax请求存在跨域无权限访问的问题,甭管你静态网页,动态网页,web服务,WCF,只要是跨域的请求,一律不准。
2.但是web网页上调用js文件是却不受跨域的影响(凡是有‘src’这个属性的标签都拥有跨域能力,比如<script><img><iframe>)。
3.于是可以判断,当前阶段想通过纯web端(ActiveX空间、服务端代理、属于未来的HTML5之Websocket等方式不算)跨域访问数据只有一种可能,那就是在远程服务器上设法把数据装进js格式文件里,供客户调用和进一步处理。
4.恰巧我们知道一种叫JSON的纯字符数据格式可以简洁地描述复杂数据,更妙的的是JSON还被js原生支持,所以在客户端几乎可以随心所欲的处理这种格式的数据。
5.这样解决方案就呼之欲出了,web客户端通过与调用脚本一模一样的方式,来调用跨域服务器生成的js格式文件(一般以JSON为后缀),显而易见,服务器要动态生成JSON文件,目的是把客户端需要的数据装进去。
6.客户端在对JSON文件调用成功之后,也就获得了自己所需的数据,剩下的就是按照自己方法处理和展现数据了。这种获取远程数据的方式看起来非常像Ajax,但其实不一样。
7.为了便于客户端使用数据,逐渐形成了一种非正式传输协议,即JSON,该协议的一个要点就是允许用户传递一个callback参数到服务端,然后服务端就用这个callback参数作为函数名包裹所需JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回的数据了。
 
JSONP的客户端具体实现
不管是jQuery也好,extjs也罢,又或者是其他支持jsonp的框架,他们幕后所做的工作都是一样的。下面就循序渐进地说说jsonp的客户端实现:
 
1.我们知道,哪怕跨域js文件中的代码(当然指符合web脚本安全策略的),web页面也是可以喝无条件执行的。
远程服务器remoteserver.com根目录下有个remote.js文件代码如下:
alert(‘我是远程文件‘);

本地服务器localserver.com下有个jsonp.html页面代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body>

</body>
</html>

毫无疑问,页面讲弹出一个提示框,显示跨域调用成功。

2.现在我们在jsonp.html页面定义一个函数,然后在远程remote.js中传入数据进行调用。

jsonp.html页面代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript">
    var localHandler = function(data){
        alert(我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是: + data.result);
    };
    </script>
    <script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
</head>
<body>

</body>
</html>

remote.js文件代码如下:

localHandler({"result":"我是远程js带来的数据"});

运行之后查看结果,页面成功弹出提示窗口,显示本地函数被跨域的远程js调用成功,并且还接收到了远程js带来的数据。 
很欣喜,跨域远程获取数据的目的基本实现了,但是又一个问题出现了,我怎么让远程js知道它应该调用的本地函数叫什么名字呢?毕竟是jsonp的服务者都要面对很多服务对象,而这些服务对象各自的本地函数都不相同啊?我们接着往下看。

3、聪明的开发者很容易想到,只要服务端提供的js脚本是动态生成的就行了呗,这样调用者可以传一个参数过去告诉服务端 "我想要一段调用XXX函数的js代码,请你返回给我",于是服务器就可以按照客户端的需求来生成js脚本并响应了。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script type="text/javascript">
    // 得到航班信息查询结果后的回调函数
    var flightHandler = function(data){
        alert(你查询的航班结果是:票价  + data.price +  元, + 余票  + data.tickets +  张。);
    };
    // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
    var url = "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998&callback=flightHandler";
    // 创建script标签,设置其属性
    var script = document.createElement(script);
    script.setAttribute(src, url);
    // 把script标签加入head,此时调用开始
    document.getElementsByTagName(head)[0].appendChild(script); 
    </script>
</head>
<body>

</body>
</html>

这次代码不再直接吧js文件写死,而是编码实现动态查询,而这也是jsonp客户端实现的核心部分,本利中的重点也就在于如何完成jsonp调用的全过程。

我们看到调用的Url中传递了一个code参数,告诉服务器我们要查的是CA1998次航班的信息,而callback参数告诉服务器,我们本地回调函数叫flightHandler,所以请把查询结果传入这个函数中进行调用。所以服务器这个叫做flightResult.aspx的页面生成了一段这样的代码提供给jsonp.html 

(服务端的实现这里就不演示了,与你选用的语言无关,说到底就是拼接字符串):

flightHandler({
    "code": "CA1998",
    "price": 1780,
    "tickets": 5
});

我们看到,传递给flightHandler函数的是一个json,它描述了航班的基本信息。运行一下页面,成功弹出提示窗口,jsonp的执行全过程顺利完成! 

4、到这里为止的话,相信你已经能够理解jsonp的客户端实现原理了吧?剩下的就是如何把代码封装一下,以便于与用户界面交互,从而实现多次和重复调用。

jQuery如何实现jsonp调用?  

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
     <title>Untitled Page</title>
      <script type="text/javascript" src=jquery.min.js"></script>
      <script type="text/javascript">
     jQuery(document).ready(function(){ 
        $.ajax({
             type: "get",
             async: false,
             url: "http://flightQuery.com/jsonp/flightResult.aspx?code=CA1998",
             dataType: "jsonp",
             jsonp: "callback",//传递给请求处理程序或页面的,·用以获得jsonp回调函数名的参数名(一般默认为:callback)
             jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
             success: function(json){
                 alert(您查询到航班信息:票价:  + json.price +  元,余票:  + json.tickets +  张。);
             },
             error: function(){
                 alert(fail);
             }
         });
     });
     </script>
     </head>
  <body>
  </body>
</html>

 

是不是有点奇怪?为什么我这次没有写flightHandler这个函数呢?而且竟然也运行成功了! 
这就是jQuery的功劳了,jquery在处理jsonp类型的ajax时(虽然jquery也把jsonp归入了ajax,但其实它们真的不是一回事儿),自动帮你生成回调函数并把数据取出来供success属性方法来调用,是不是很爽呀? 

ajax与jsonp的异同

1、ajax和jsonp这两种技术在调用方式上"看起来"很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jquery和ext等框架都把jsonp作为ajax的一种形式进行了封装。 

2、但ajax和jsonp其实本质上是不同的东西。ajax的核心是通过XmlHttpRequest获取非本页内容,而jsonp的核心则是动态添加<script>标签来调用服务器提供的js脚本。 

3、所以说,其实ajax与jsonp的区别不在于是否跨域,ajax通过服务端代理一样可以实现跨域,jsonp本身也不排斥同域的数据的获取。 

4、还有就是,jsonp是一种方式或者说非强制性协议,如同ajax一样,它也不一定非要用json格式来传递数据,如果你愿意,字符串都行,只不过这样不利于用jsonp提供公开服务。 

总而言之,jsonp不是ajax的一个特例,哪怕jquery等巨头把jsonp封装进了ajax,也不能改变这一点!

 









前端面试题

https协议http状态码前端性能优化前端跨域jsonp实现原理cookiesession变量提升作用域闭包写一个三角形callapply排序算法手写JS原型继承手写JS发布订阅类手写事件通用类手写Object深复制方法手写vuex实现原理在项目中遇到难点怎么克服... 查看详情

八.全文检索elasticsearch经典入门-深入理解elasticsearch核心原理(代码片段)

...后就可以把ES融入到企业级项目开发了。本篇文章我们将深入了解一下ElasticSearch原理性的东西,我会以面试题总结的方式来展开。常见面试题为什么要选择全文搜索引擎,而不直接用like可能你会觉得问这个问题的面试官... 查看详情

2021年8月前端面试题最新出炉-深入剖析&资料汇总

...回顾、查阅。建议收藏哦!文章目录一、前端知识点深入汇总,划重点!1.HTTP跨域的10种解决方案2.HTTP相关面试题3.Chrome浏览器的渲染原理4.数组常用的操作方法5.是否改变原数组方法总结6.JS的三个方法& 查看详情

面试官问:如何理解虚拟dom,我是这样回答的

...问Vue和React框架的,不仅要精通应用层面,还要更深入的理解原理。确实,现在前端岗位的竞争日渐激烈,求职者要对比项目经验,工作成果等等,如果在技术能力上翻车就犯不上了。源码逐渐成为各大厂... 查看详情

前端面试(代码片段)

...建对象的方式怎么实现继承闭包同步和异步的区别this的理解原型链jsonp原理(手写)判断是一个数组深拷贝dom操作创建dom元素删除dom元素jquery你觉得jquery有哪些好处还用过什么工具库js规范amdcommonjsesmumdrequirejs怎么写jq插件怎么给数... 查看详情

前端跨域之jsonp实现原理及.net下jsonp的实现

jsonp的本质是通过script标签的src属性请求到服务端,拿到到服务端返回的数据,因为src是可以跨域的。前端通过src发送跨域请求时在请求的url带上回调函数,服务端收到请求时,接受前端传过来的回掉函数名称,将其拼接成js函... 查看详情

jsonp原理解析

...服务端需要配置的地方会较多。这篇解析一下jsonp的实现原理。基本原理基本原理很容易说明白,在html页面中有一些标签是不受跨域限制的,比如img, 查看详情

深入理解浏览器工作原理(转)(代码片段)

 [1]组成[2]内核[3]渲染流程[4]资源加载[5]缓存[6]网页解析[7]硬件加速[8]重绘回流前面的话  浏览器(browserapplication)是专门用来访问和浏览万维网页面的客户端软件,也是现代计算机系统中应用最为广泛的软件之一,其重要... 查看详情

前端面试--ajax和jsonp跨域(代码片段)

<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metanam 查看详情

深入理解rcu|核心原理

深入理解RCU|核心原理                查看详情

面试题总结

...nbsp;前言手写事件模型及事件代理/委托前端性能优化闭包原理及应用手写Function.bind函数手写数组快速排序/去重JS的定义提升跨域JSONP原理将url的查询参数解析成字典对象函数节流设计模式css垂直居中方法自适应布局移动端自适应... 查看详情

深入理解stream之原理剖析

...然是JDK1.8。所以,我们有必要聊一聊Java8的一些新特性。深入理解lambda的奥秘深入理解Stream之原理剖析深入理解Stream之foreach源码解析深入浅出NPE神器Optional谈谈接口默认方法与静态方法深入浅出重复注解与类型注解深入浅出JVM元... 查看详情

前端面试要点

...对于前端开发来说,如果说社招更看重对前端技术体系的深入理解,以及解决问题的能力话,那校招更看重的其实是基本功和学习能力(或者说是潜力)。但其实,无论是社招还是校招,面试的时候都会问到一些曾经操作过的项... 查看详情

深入理解aqs(代码片段)

文章目录深入理解AQSAQS概念特点AOS自定义实现锁ReentrantLock原理非公平锁实现原理加锁解锁原理竞争失败原理RenntrantLock可重入的原理可打断原理可打断模式公平锁实现原理非公平锁实现公平锁实现读写锁ReentrantReadWriteLock注意事项... 查看详情

[转]深入理解batchnormalization批标准化

这几天面试经常被问到BN层的原理,虽然回答上来了,但还是感觉答得不是很好,今天仔细研究了一下BatchNormalization的原理,以下为参考网上几篇文章总结得出。  BatchNormalization作为最近一年来DL的重要成果,已经广泛被证明... 查看详情

深入理解多线程——moniter的实现原理(代码片段)

深入理解多线程(四)——Moniter的实现原理收录于话题#和并发编程有关的那点事儿13个点击上方“Hollis”关注我,精彩内容第一时间呈现。全文字数:1200阅读时间:3分钟本文是《深入理解多线程系列文章》的第四篇。点击查看... 查看详情

hashmap工作原理深入理解jvm正则

HashMap工作原理:http://www.importnew.com/7099.html;http://blog.csdn.net/ghsau/article/details/16843543;http://blog.csdn.net/ghsau/article/details/16890151。 深入理解JVM:http://www.importnew.com/17770.html 查看详情

深入理解javascripthijacking原理

    最近在整理关于JavaScript代码安全方面的资料,在查关于JavaScriptHijacking的资料时,发现关于它的中文资料很少,故特意整理一下。一.JavaScriptHijacking原理其实JavaScriptHijacking和CSRF攻击的思想很类似,关于CSRF攻击... 查看详情