JSONP基础知识详解


Posted in Javascript onMarch 19, 2017

前面的话

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。相反,它们使用?搜?问?闹担?市砜突Ф酥付ㄒ桓龊????缓笫褂煤???ヌ畛湎煊ΑP矶嘀С?SONP的服务都能分辨出这个参数名。另一个常见的参数名称是callback,为了让使用到的服务支持类似特殊的需求,就需要在代码上做一些修改了

JSONP由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数。回调函数的名字一般是在请求中指定的。而数据就是传入回调函数中的JSON数据

http://freegeoip.net/json/?callback=handleResponse

这个URL是在请求一个JSONP地理定位服务。通过?搜?址??粗付?SONP服务的回调参数是很常见的,就像上面的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,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" 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如下

https://www.baidu.com/s?wd=a

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>

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
js导出txt示例代码
Jan 14 Javascript
jQuery实现鼠标经过时出现隐藏层文字链接的方法
Oct 12 Javascript
JS组件系列之Bootstrap Icon图标选择组件
Jan 28 Javascript
Node.js插件安装图文教程
May 06 Javascript
jQuery EasyUI框架中的Datagrid数据表格组件结构详解
Jun 09 Javascript
javascript容错处理代码(屏蔽js错误)
Jan 20 Javascript
bootstrap fileinput 插件使用项目总结(经验)
Feb 22 Javascript
js实现下拉菜单效果
Mar 01 Javascript
Vue下的国际化处理方法
Dec 18 Javascript
vue 2.8.2版本配置刚进入时候的默认页面方法
Sep 21 Javascript
学前端,css与javascript重难点浅析
Jun 11 Javascript
Vue触发input选取文件点击事件操作
Aug 07 Javascript
jQuery中table数据的值拷贝和拆分
Mar 19 #Javascript
js实现旋转木马效果
Mar 17 #Javascript
jQuery实现验证码功能
Mar 17 #Javascript
基于vue.js轮播组件vue-awesome-swiper实现轮播图
Mar 17 #Javascript
node操作mysql数据库实例详解
Mar 17 #Javascript
vue.js从安装到搭建过程详解
Mar 17 #Javascript
超简单的Vue.js环境搭建教程
Mar 17 #Javascript
You might like
PHP入门学习的几个不错的实例代码
2008/07/13 PHP
php读取xml实例代码
2010/01/28 PHP
WordPress中邮件的一些修改和自定义技巧
2015/12/15 PHP
简单了解WordPress开发中update_option()函数的用法
2016/01/11 PHP
ThinkPHP5 框架引入 Go AOP,PHP AOP编程项目详解
2020/05/12 PHP
javascript编程起步(第三课)
2007/02/27 Javascript
ext checkboxgroup 回填数据解决
2009/08/21 Javascript
JavaScript中:表达式和语句的区别[译]
2012/09/17 Javascript
jQuery设置div一直在页面顶部显示的方法
2013/10/24 Javascript
Jquery中国地图热点效果-鼠标经过弹出提示层信息的简单实例
2014/02/12 Javascript
js实现接收表单的值并将值拼在表单action后面的方法
2015/11/23 Javascript
Android中Okhttp3实现上传多张图片同时传递参数
2017/02/18 Javascript
jQuery实现表格奇偶行显示不同背景色 就这么简单
2017/03/13 Javascript
JS实现根据详细地址获取经纬度功能示例
2019/04/16 Javascript
wx-charts 微信小程序图表插件的具体使用
2019/08/18 Javascript
基于iview-admin实现动态路由的示例代码
2019/10/02 Javascript
React学习之受控组件与数据共享实例分析
2020/01/06 Javascript
Python导出DBF文件到Excel的方法
2015/07/25 Python
如何在Django配置文件里配置session链接
2019/08/06 Python
Python3的socket使用方法详解
2020/02/18 Python
Python3.6 中的pyinstaller安装和使用教程
2020/03/16 Python
利用SVG和CSS3来实现一个炫酷的边框动画
2015/07/22 HTML / CSS
德国家具在线:Fashion For Home
2017/03/11 全球购物
本科生求职简历的自我评价
2013/10/21 职场文书
党员组织关系介绍信
2014/02/13 职场文书
企业文化理念标语
2014/06/10 职场文书
婚礼新人答谢词
2015/01/04 职场文书
2015年安全保卫工作总结
2015/05/14 职场文书
2015年学校党建工作总结
2015/05/19 职场文书
圆明园纪录片观后感
2015/06/03 职场文书
大学生奶茶店创业计划书
2019/06/25 职场文书
python3美化表格数据输出结果的实现代码
2021/04/14 Python
Python基于百度API识别并提取图片中文字
2021/06/27 Python
Spring Boot 排除某个类加载注入IOC的操作
2021/08/02 Java/Android
使用Oracle命令进行数据库备份与还原
2021/12/06 Oracle
PYTHON InceptionV3模型的复现详解
2022/05/06 Python