JSONP是JSON with padding(填充式JSON或参数式JSON)的简写,是应用JSON的一种新方法,常用于服务器与客户端跨源通信,在后来的Web服务中非常流行。本文将详细介绍JSONP

 JSONP的基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来

  当通过<script>元素调用数据时,响应内容必须用javascript函数名和圆括号包裹起来。而不是发送这样一段JSON数据,这就是JSONP中P的意义所在

  1. [1, 2, {"buckle": "my shoe"}]

  JSONP看起来与JSON差不多,只不过是被包含在函数调用中的JSON,它会发送这样一个包裹后的JSON响应:

  1. handleResponse([l, 2, {"buckle": "my shoe"}])

  

 包裹后的响应会成为<script>元素的内容,它先判断JSON编码后的数据,然后把它传递给handleResponse()函数

  在实践中,支持JSONP的服务不会强制指定客户端必须实现的回调函数名称,比如handleResponse。相反,它们使用査询参数的值,允许客户端指定一个函数名,然后使用函数名去填充响应。许多支持JSONP的服务都能分辨出这个参数名。另一个常见的参数名称是callback,为了让使用到的服务支持类似特殊的需求,就需要在代码上做一些修改了

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

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

  

这个URL是在请求一个JSONP地理定位服务。通过査询字符串来指定JSONP服务的回调参数是很常见的,就像上面的URL所示,这里指定的回调函数的名字叫handleResponse()

  JSONP是通过动态<script>元素来使用的,使用时可以为src属性指定一个跨域URL。这里的<script>元素与<img>元素类似,都有能力不受限制地从其他域加载资源。因为JSONP是有效的javascript代码,所以在请求完成后,即在JSONP响应加载到页面中以后,就会立即执行

  1. function handleResponse(response){
  2. alert ("You're at IP address " + response.ip + ", which is in " + response.city + ", "+ response.region_name);
  3. }
  4. var script = document.createElement("script");
  5. 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事件处理程序,但目前还没有得到任何浏览器支持。为此,开发人员不得不使用计时器检测指定时间内是否接收到了响应。但就算这样也不能尽如人意,毕竟不是每个用户上网的速度和带宽都一样

简易示例

【前端】

  1. <button id="btn">获取信息</button>
  2. <img id="img" height="16" style="display:none" src="data:image/gif;base64,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" alt="loading">
  3. <div id="result"></div>
  4. <script>
  5. var add = (function(){
  6. var counter = 0;
  7. return function(){
  8. return ++counter;
  9. }
  10. })();
  11. function loadScript(url){
  12. loadScript.mark = 'load';
  13. var script = document.createElement("script");
  14. script.type = "text/javascript";
  15. script.src = url;
  16. script.onload = function(){
  17. img.style.display = 'none';
  18. btn.removeAttribute('disabled');
  19. }
  20. document.body.appendChild(script);
  21. }
  22. function test(data){
  23. var sum = add() - 1;
  24. if(sum < data.length ){
  25. result.innerHTML += data[sum];
  26. }
  27. }
  28. btn.onclick = function(){
  29. img.style.display = 'inline-block';
  30. btn.setAttribute('disabled','');
  31. loadScript('https://www.webhuochai.com/test/getData.php?callback=test');
  32. }
  33. </script>

  

【后端】

  1. <?php
  2. function test_input($data) {
  3. $data = trim($data);
  4. $data = stripslashes($data);
  5. $data = htmlspecialchars($data);
  6. return $data;
  7. }
  8. $arr = [1,2,3,4,5];
  9. echo test_input($_GET['callback']) ."(" .json_encode($arr) .");";
  10. ?>

  

百度搜索框

  百度搜索框就是使用了JSONP的技术,在百度搜索的URL中,有用的查询如下

  1. https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=123&&cb=a

  

结果为:

  1. a({q:"123",p:false,s:["12306","12306铁路客户服务中心","12308汽车订票官网","12306火车票网上订票官网","12333","12315","12345","12333社保查询网","123网址之家","12366"]});

  

 所以,wd为关键词,cb用来JSONP的函数名。在获取的数据中,s为以关键词开始的数据组成的数据

  百度搜索的关键URL如下

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

  

wd为关键词,当wd=a时,将打开关键词为a的网页

  1. <style>
  2. body{margin: 0;}
  3. ul{margin: 0;padding: 0;list-style: none;}
  4. a{color:inherit;text-decoration: none;}
  5. input{padding: 0;border: 0;}
  6. .box{width: 340px;height: 38px;border: 2px solid gray;}
  7. .con{overflow: hidden;}
  8. .input{float: left;width: 300px;height: 38px;}
  9. .search{width: 38px;height: 38px;float: right;background: url('http://sandbox.runjs.cn/uploads/rs/26/ddzmgynp/search.png') 0 -38px;}
  10. .list{position: absolute;width: 298px;border: 1px solid #e6e8e9; overflow: hidden;}
  11. .in{line-height: 30px;border-bottom: 1px solid lightblue;cursor:pointer;text-indent: 1em;}
  12. .list .in:last-child{margin-bottom: -1px;}
  13. .in:hover{background-color: #f9f9f9;}
  14. </style>
  15.  
  16. <div class="box" id="box">
  17. <div class="con">
  18. <input class="input" id="search">
  19. <a target="_blank" id="btn" href="javascript:;" class="search"></a>
  20. </div>
  21. <ul class="list" id="list"></ul>
  22. </div>
  23. <script>
  24. function loadScript(url){
  25. loadScript.mark = 'load';
  26. var script = document.createElement("script");
  27. script.type = "text/javascript";
  28. script.src = url;
  29. document.body.appendChild(script);
  30. }
  31. function callback(data){
  32. if(data){
  33. var arr = data.s;
  34. var html = '';
  35. for(var i = 0,len = arr.length; i < len; i++){
  36. html+= "<li class='in'><a href='https://www.baidu.com/s?wd="+ arr[i]+"' target='_blank' style='display:block'>" + arr[i]+ "</a></li>"
  37. }
  38. list.innerHTML = html;
  39. }
  40. }
  41. search.onkeyup = function(e){
  42. e = e || event;
  43. if(e.keyCode == '13'){
  44. window.open('https://www.baidu.com/s?wd=' + this.value);
  45. }
  46. if(this.value){
  47. if(search.data != this.value){
  48. btn.setAttribute('href','https://www.baidu.com/s?wd=' + this.value);
  49. var that = this;
  50. loadScript("https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd=" + that.value + "&&cb=callback");
  51. }
  52. }else{
  53. list.innerHTML = '';
  54. }
  55. search.data = this.value;
  56. }
  57. search.onclick = function(e){
  58. e = e || event;
  59. list.style.display = 'block';
  60. if(e.stopPropagation){
  61. e.stopPropagation();
  62. }else{
  63. e.cancelBubble = true;
  64. }
  65. }
  66. document.onclick = function(){
  67. list.style.display = 'none';
  68. }
  69. </script>

  

jsonp: js跨域的更多相关文章

  1. JS跨域(ajax跨域、iframe跨域)解决方法及原理详解(jsonp)

    这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...

  2. 【转】JS跨域(ajax跨域、iframe跨域)解决方法及原理详解(jsonp)

    这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...

  3. 初步了解关于js跨域问题-jsonp

    js跨域问题是指在js在不同的域中进行数据传输或者数据通信,比如通过ajax向不同的域请求数据(说到ajax,不可避免的就会遇到两个问题:一是ajax是如何传递数据的?二是ajax是如何实现跨域的?) ...

  4. js跨域交互之jsonp - 看完就能让你了解jsonp原理 (原)

    跨域? 跨域的安全限制都是对浏览器端来说的,服务器端是不存在跨域安全限制的. 同源策略? 一般来说 a.com 的网页无法直接与 b.com的服务器沟通, 浏览器的同源策略限制从一个源加载的文档或脚本 ...

  5. js跨域请求jsonp解决方案-最简单的小demo

    这里说的js跨域是指通过js在不同的域之间进行数据传输或通信,比如用ajax向一个不同的域请求数据,或者通过js获取页面中不同域的框架中(iframe)的数据.只要协议.域名.端口有任何一个不同,都被 ...

  6. js跨域请求(jsonp)

    jsonp是跨域请求的手段之一. jsonp的原理: 先来看看下面这段代码 <!DOCTYPE html> <html lang="en"> <hea ...

  7. js跨域问题解释 使用jsonp或jQuery的解决方案

    js跨域及解决方案 1.什么是跨域 我们经常会在页面上使用ajax请求访问其他服务器的数据,此时,客户端会出现跨域问题. 跨域问题是由于javascript语言安全限制中的同源策略造成的. 简单来说, ...

  8. js跨域请求方式 ---- JSONP原理解析

    这篇文章主要介绍了js跨域请求的5中解决方式的相关资料,需要的朋友可以参考下     跨域请求数据解决方案主要有如下解决方法:   1 2 3 4 5 JSONP方式 表单POST方式 服务器代理 H ...

  9. JS跨域:jsonp、跨域资源共享、iframe+window.name

    JS跨域:jsonp.跨域资源共享.iframe+window.name :https://www.cnblogs.com/doudoublog/p/8652213.html JS中的跨域 请求跨域有 ...

随机推荐

  1. 解决Vue的表格中,expand只有某些行需要展开的问题。

    element UI里的表格里,type="expand"的话,所有行都有展开的选项,然而实际中有些行根据判断不需要展开,而element目前对这个问题还不是很友好,现在有个可以通 ...

  2. 检查arg是方法还是函数?

    from types import MethodType,FunctionType def check(arg): """ 检查arg是方法还是函数? :param ar ...

  3. vue.js 拦截器

    document.cookie = "mylogin=1";//1:登陆成功:保存登录状态 main.js router.beforeEach((to, from, next) = ...

  4. vue 项目 npm install 报错解决

    node-sass 安装报错解决办法 2017年04月15日 14:34:25 阅读数:20189 E:\kibana>npm install node-sass > node-sass@ ...

  5. C语言预处理命令的使用

    cppreference.com -> 预处理命令 -> 详细说明 预处理命令 #,## # 和 ## 操作符是和#define宏使用的. 使用# 使在#后的首个参数返回为一个带引号的字符 ...

  6. LeetCode:二叉树的层次遍历||【107】

    LeetCode:二叉树的层次遍历||[107] 题目描述 给定一个二叉树,返回其节点值自底向上的层次遍历. (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历) 例如:给定二叉树 [3,9,2 ...

  7. iOS代码瘦身实践

    1 分析当前ipa的组成 一般一个ipa会包含: 1) 资源文件 本地文件:数据.配置.数据库等等 字体文件 图片资源 2)  源代码 通过生成linkmap文件,分析源代码生成的编译文件的大小.在B ...

  8. iOS 给 ViewController 减负 之 UITableView

    今天看了一些博客文章分享了如何给ViewController 瘦身的问题, 其中一个就是tableView. 的确,随着产品迭代,VC里面可能越来越臃肿,有时候真的需要好好进行一次瘦身.可能是参考的博 ...

  9. hostname -f 失败解决办法

    $ hostname fzk $ uname -n fzk 当 hostname -f 时报错:未搜索到主机名 产生这个原因时因为  /etc/hosts和/etc/sysconfig/network ...

  10. new Date(dateString)

    xxxx-xx-xx xx:xx:xx chrome firefox opera xxxx/xx/xx xx:xx:xx chrome firefox opera safari ios(苹果手机只认此 ...