当前位置: 移动技术网 > IT编程>开发语言>JavaScript > JSONP基础知识详解

JSONP基础知识详解

2019年03月20日  | 移动技术网IT编程  | 我要评论

前面的话

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数据

这个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>

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持移动技术网!

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网