JSONP基础知识详解
前面的话
jsonp是json with padding(填充式json或参数式json)的简写,是应用json的一种新方法,常用于务器与客户端跨源通信,在后来的web服务中非常流行。本文将详细介绍jsonp
基础
jsonp的基本思想是,网页通过添加一个<script>元素,向服务器请求json数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来
当通过<script>元素调用数据时,响应内容必须用javascript函数名和圆括号包裹起来。而不是发送这样一段json数据,这就是jsonp中p的意义所在
[1, 2, {"buckle": "my shoe"}]
jsonp看起来与json差不多,只不过是被包含在函数调用中的json,它会发送这样一个包裹后的json响应:
handleresponse([l, 2, {"buckle": "my shoe"}])
包裹后的响应会成为<script>元素的内容,它先判断json编码后的数据,然后把它传递给handleresponse()函数
在实践中,支持jsonp的服务不会强制指定客户端必须实现的回调函数名称,比如handleresponse。相反,它们使用査询参数的值,允许客户端指定一个函数名,然后使用函数名去填充响应。许多支持jsonp的服务都能分辨出这个参数名。另一个常见的参数名称是callback,为了让使用到的服务支持类似特殊的需求,就需要在代码上做一些修改了
jsonp由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的json数据
http://freegeoip.net/json/?callback=handleresponse
这个url是在请求一个jsonp地理定位服务。通过査询字符串来指定jsonp服务的回调参数是很常见的,就像上面的url所示,这里指定的回调函数的名字叫handleresponse()
jsonp是通过动态<script>元素来使用的,使用时可以为src属性指定一个跨域url。这里的<script>元素与<img>元素类似,都有能力不受限制地从其他域加载资源。因为jsonp是有效的javascript代码,所以在请求完成后,即在jsonp响应加载到页面中以后,就会立即执行
function handleresponse(response){ alert ("you're at ip address " + response.ip + ", which is in " + response.city + ", "+ response.region_name); } var script = document.createelement("script"); script.src = "http://freegeoip.net/json/?callback=handleresponse"; document.body.insertbefore(script, document.body.firstchild);
jsonp之所以在开发人员中极为流行,主要原因是它非常简单易用,老式浏览器全部支持,服务器改造非常小。与图像ping相比,它的优点在于能够直接访问响应文本,支持在浏览器与服务器之间双向通信
使用<script>元素进行ajax传输,不受同源策略的影响,因此可以使用它们从其他的服务器请求数据;而且,包含json编码数据的响应体会自动解码(即执行)
不过,jsonp也有两点不足:首先,jsonp是从其他域中加载代码执行。如果其他域不安全,很可能会在响应中夹带一些恶意代码,而此时除了完全放弃jsonp调用之外,没有办法追究。因此在使用不是自己运维的web服务时,一定得保证它安全可靠;其次,要确定jsonp请求是否失败并不容易。虽然html5给<script>元素新增了一个onerror事件处理程序,但目前还没有得到任何浏览器支持。为此,开发人员不得不使用计时器检测指定时间内是否接收到了响应。但就算这样也不能尽如人意,毕竟不是每个用户上网的速度和带宽都一样
简易示例
【前端】
<button id="btn">获取信息</button> <img id="img" height="16" style="display:none" src="data:image/gif;base64,r0lgodlhiaagalmaap///7ozs/v7+9bw1uhh4fly8rq6uogbgtq0naebarsbg8texjexl/39/vruvaaaach/c05fvfndqvbfmi4waweaaaah+qqfbqaaacwaaaaaiaagaaae5xdissllrornp0pknrcdfhxvoljlejquosgopsyt4rownssvyw1ica16k8mmmrkcbjskbtfdazyuaekqcfxiq2hgqrfvaqeeijnxvdw6xne4yagrjubcwe60smqudnd4rz1zaqznfagdd0hihh12cee9kjaevlycxig7basmb6slnj87paqbskikoqusnbmdmdc2txqlkuhziytywtxify6be8wjt5yevpjivxnagmlht0vnoggyf0dzxs7apdpb309rnhog5gdqxgldac457d1zz/v/nmom82xihqjykhkp1ozmaddeaaah+qqfbqaaacwaaaaagaaxaaaechdisaskneujfkohs4muyljikmjiv54soypsa0wmlsnqotetbw52mg0ajhypbxioeqrny8v0qfznw+ggwljki4lbqx1ibgjmkrighwjrzcdti2/gh7d9qn774wqgayoefwcchiv/gymdho+qkzktr3p7eqah+qqfbqaaacwbaaaahqaoaaaechdiswdanesnhhjzwe2duseo5sjkkb2hokgyfld1cb/dneoilkti2plyukgeatmbaaacsygbedyd4zn1yiemh0scqqgyehnmtnnaksqjxmbuueypi9ecau/ufnnzeup9vbqebofolmfxwhnoqw6rweoceqah+qqfbqaaacwhaaaagqaraaaeardicdzznovndsvfbhbddpwzgohbge3nqaki0ayejeqogmqdlkenazbujhra0cobyhlvskm4saaawkahcfawtu0a4rxzfwjnzxfwjjwb9ptihru5dvghl+/7nqmbggo/fykhcx8aiameeqah+qqfbqaaacwoaaaaegayaaaezxcwaaq9odamdouai17mcydhwa3mcypb1rooxbktmsbt944bu6zcqcbqiwpb4jaihick86irtb20qvwp7xq/fyv4tnwnz4oqwoeigl0hx/eqsli69bociktke2vvdap5d1p0cw4rach5baufaaaala4aaaasab4aaasakbgcqr3ybimxvkeimsxxhcffpizqbatxisbclibgand+ijygq2i4haamwxbgnhj8bebzgpnnjz7lwpnfdlvglgjmdnw/5drcrhae3xbkm6fqwot1xdnpwcvcjgcjmgeiecyocqlrf4ymbiojvv2ccxzvcoohbwgrcaikcmfujheaifkebquaaaasdwababeahwaabhsqyakgorivelinnoflbjem1bcifbdcbmutkqdtn0cujru5njqrymh5vifttkjcoj2hqjqrheqvqguu+uw6awgewxkoo55lxiihodjky8pbothpxmpayi+hkzoeewktdhkzghmidcoihiuhfbmojxinlr4kcw1odalxsxeaifkebquaaaascaaoabgaegaabgwqyekrcdgbyvvmoof5ilanaiogkroch9hacd3mfmhubzmhibtgwjmbfoldb4goggbcackrcaauwamzowjqexysqsjgwj0kqvkaltiyphp1lbfttp10is6mt5gdvfx1brn8ftsvcaqdob9+kheaifkebquaaaasagasab0adgaabhgqyemrbeps4bqdqzbdr5ichmwegufqgwkakbwwwsihc4lonsxhbscsqoosscgqdjiwwohqnaxwbiyjnxeofciewdi9jczesey7gwmm5doeww4jjoypqq743u1wctv0cgfzbhj5xclfhyd/ewznhoyvdgiofhkqnreaifkebquaaaasaaapabkaeqaabgeqquqrudjrw3vaycz5x2ie6ekckaootasi7ytntq046bbsnctvitz4aotmwkzbic6h6cvajacct0cubtgatg5ntcu9gkidempjg5ybbopwlnvzlwtqyknzagzwahomb2m3ggshsrsrach5baufaaaalaeacaarabgaaarcmkr0gl34npkuyycacamyhbijkgi2uw02vhft33iu7yididad4/ereygdlu/nubaoj9dvc2ecdgfayiuaxs3bboh6mic5iap5eh5fk2exc4tpgwzyiyfgvhembbeaifkebquaaaasaaacaa4ahqaabhmqyanyovislfdgxbj808ep5krwv8qeg+prcoeoiokmwjk0ekcu54h9aoghkgximzgaapqzcccu2ax2o6nuud2pmjcyha4l0udm/ljydcngfgakjqe5yh0wubybauyfbifkhwabgxkdgx5lgxphaxcpbisrads=" alt="loading"> <div id="result"></div> <script> var add = (function(){ var counter = 0; return function(){ return ++counter; } })(); function loadscript(url){ loadscript.mark = 'load'; var script = document.createelement("script"); script.type = "text/javascript"; script.src = url; script.onload = function(){ img.style.display = 'none'; btn.removeattribute('disabled'); } document.body.appendchild(script); } function test(data){ var sum = add() - 1; if(sum < data.length ){ result.innerhtml += data[sum]; } } btn.onclick = function(){ img.style.display = 'inline-block'; btn.setattribute('disabled',''); loadscript('https://www.webhuochai.com/test/getdata.php?callback=test'); } </script>
【后端】
<?php function test_input($data) { $data = trim($data); $data = stripslashes($data); $data = htmlspecialchars($data); return $data; } $arr = [1,2,3,4,5]; echo test_input($_get['callback']) ."(" .json_encode($arr) .");"; ?>
百度搜索框
百度搜索框就是使用了jsonp的技术,在百度搜索的url中,有用的查询如下
https://sp0.baidu.com/5a1fazu8aa54nxgko9wtanf6hhy/su?wd=123&&cb=a
结果为:
a({q:"123",p:false,s:["12306","12306铁路客户服务中心","12308汽车订票官网","12306火车票网上订票官网","12333","12315","12345","12333社保查询网","123网址之家","12366"]});
所以,wd为关键词,cb用来jsonp的函数名。在获取的数据中,s为以关键词开始的数据组成的数据
百度搜索的关键url如下
wd为关键词,当wd=a时,将打开关键词为a的网页
<style> body{margin: 0;} ul{margin: 0;padding: 0;list-style: none;} a{color:inherit;text-decoration: none;} input{padding: 0;border: 0;} .box{width: 340px;height: 38px;border: 2px solid gray;} .con{overflow: hidden;} .input{float: left;width: 300px;height: 38px;} .search{width: 38px;height: 38px;float: right;background: url('http://sandbox.runjs.cn/uploads/rs/26/ddzmgynp/search.png') 0 -38px;} .list{position: absolute;width: 298px;border: 1px solid #e6e8e9; overflow: hidden;} .in{line-height: 30px;border-bottom: 1px solid lightblue;cursor:pointer;text-indent: 1em;} .list .in:last-child{margin-bottom: -1px;} .in:hover{background-color: #f9f9f9;} </style> <div class="box" id="box"> <div class="con"> <input class="input" id="search"> <a target="_blank" id="btn" href="javascript:;" rel="external nofollow" class="search"></a> </div> <ul class="list" id="list"></ul> </div> <script> function loadscript(url){ loadscript.mark = 'load'; var script = document.createelement("script"); script.type = "text/javascript"; script.src = url; document.body.appendchild(script); } function callback(data){ if(data){ var arr = data.s; var html = ''; for(var i = 0,len = arr.length; i < len; i++){ html+= "<li class='in'><a href='https://www.baidu.com/s?wd="+ arr[i]+"' target='_blank' style='display:block'>" + arr[i]+ "</a></li>" } list.innerhtml = html; } } search.onkeyup = function(e){ e = e || event; if(e.keycode == '13'){ window.open('https://www.baidu.com/s?wd=' + this.value); } if(this.value){ if(search.data != this.value){ btn.setattribute('href','https://www.baidu.com/s?wd=' + this.value); var that = this; loadscript("https://sp0.baidu.com/5a1fazu8aa54nxgko9wtanf6hhy/su?wd=" + that.value + "&&cb=callback"); } }else{ list.innerhtml = ''; } search.data = this.value; } search.onclick = function(e){ e = e || event; list.style.display = 'block'; if(e.stoppropagation){ e.stoppropagation(); }else{ e.cancelbubble = true; } } document.onclick = function(){ list.style.display = 'none'; } </script>
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!