ajax,jsonp跨域

阮一峰:浏览器同源政策及其规避方法
同源政策:同协议、同域名、同端口
阮一峰:ajax教程
ajax用XMLHttpRequest向后端发送请求,但是AJAX无法跨源
json语法;通过JSON.parse(string)将后端返回的字符串转换成JS对象
jsonp动态添加script标签实现跨域请求,但jsonp只能发送GET请求
CORS跨域,支持所有请求

json

JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
JSON 使用 Javascript语法来描述数据对象

  • JS 是一门语言,JSON 是另一门语言
  • json这门语言是道格拉斯抄袭js的语言
  • JSON 使用 Javascript语法来描述数据对象
  • 道格拉斯还写了本《javascript语言精粹》,俗称蝴蝶书,来吐槽js中垃圾的地方

json铁轨图

http://json.org

json语法

{"a":1,"name":"stage","age":24}

json里的【字符串】必须用双引号,不能用单引号!!
json没有undefinedfunction
| js数据 | json数据 |
| :—-: |:———:|
| 123| 123 |
| ‘stage’| “stage” |
| true| true |
| [‘a’, ‘b’] | [“a”, “b”] |
| {name: ‘stage’} | {“name”: “stage”} |
| null | null |
| undefined| json没有undefined |
| function fn(){}| json没有function |

浏览器同源策略

  • 同协议
  • 同域名
  • 同端口

举例来说,http://www.example.com/d/page.html这个网址,
协议是http://
域名是www.example.com
端口是80(http默认端口80,https默认端口443)。

1
2
3
4
5
http://www.example.com/d2/other.html // 同源
http://example.com/d/other.html // 不同源(域名不同)
http://v2.www.example.com/d/other.html // 不同源(域名不同)
http://www.example.com:81/d/other.html // 不同源(端口不同)
https://www.example.com // 不同源(协议不同)

不刷新页面,使用xhr发送请求局部更新数据:AJAX

AJAX - 异步的 JavaScript 和 XML
AJAX就是使用XMLHttpRequest技术向服务端发送请求
AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

  • 使用 XMLHttpRequest 发请求
  • 服务器返回 JSON 格式的字符串(后来人们不用XML,改用JSON了)
  • JS 解析 JSON(通过JSON.parse(字符串) 将JSON格式的字符串转成JS对象),并更新局部页面
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    var xhr = new XMLHttpRequest();
    xhr.open('GET', '/', true);
    xhr.onreadystatechange = function() {
    if (this.readyState == 4) {
    if (this.status >= 200 && this.status < 400) {
    // 成功!
    var string = this.responseText;
    var obj = JSON.parse(string);
    } else {
    // 失败 _(:з」∠)_
    }
    }
    };
    xhr.send();

AJAX无法跨域

同源政策规定,AJAX请求只能发给同源的网址,否则就报错。
只有 协议 + 域名 + 端口 完全一模一样才能发AJAX请求

1
2
http://www.baidu.com 不可以向 http://baidu.com 发AJAX请求
http://www.baidu.com:80 不可以向 http://www.baidu.com:81 发AJAX请求

如何解决AJAX无法跨域的问题?↓↓↓

跨域方法:jsonp

由于同源策略,我们无法从别的域名(网站)那获取数据,用jsonp可以解决这个问题。
JsonP(JSON with Padding) 是 json 的一种”使用模式”,可以让网页从别的域名(网站)那获取数据,即跨域读取数据。
它的基本思想是,网页通过动态添加<script>标签,<script>标签的src向跨域服务器请求JSON数据,同时传一个查询参数callback=随机名&时间戳,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function addScriipt(src) {
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
script.onload = function(ev){
this.parentNode.removeChild(this);; //删除script标签
}
}
window.onload = function () {
addScriipt('http://example.com/ip?callback=JQuery173625173837');
}
function JQuery173625173837(data) {//服务器收到这个请求以后,会将数据放在回调函数的参数位置(data)返回。
console.log(data.a);
};
//后端返回:
JQuery173625173837({a:123}); //由于上面定义了该方法,因此后端返回后直接执行这个方法

上面代码通过动态添加<script>标签,向服务器example.com发出请求。注意,该请求的查询字符串有一个callback参数,用来指定回调函数的名字(一般用随机数),这对于JSONP是必需的。此外还需要加一个时间戳,防止浏览器的缓存。

由于<script>标签请求的脚本会直接作为代码运行。这时,只要浏览器定义了名字为随机数的函数,该函数就会立即调用。于是请求方就能获得他要的数据。

jsonp面试题

  • 什么是jsonp

JSONP(JSON with Padding) 是 json 的一种”使用模式”,可以让网页从别的域名(网站)那获取数据,即跨域读取数据。
它的基本思想是:

  1. 网页通过动态添加<script>标签,<script>标签的src向服务器请求数据,同时传一个查询参数callback=随机名&时间戳给服务器,这种做法不受同源政策限制
  • 服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。
  • 由于<script>标签请求的脚本会直接作为代码运行。这时,只要浏览器定义了对应名字的函数,该函数就会立即调用。
  • 于是请求方就能获得他要的数据。
  • jsonp为什么不支持post方法

因为jsonp是通过动态创建<script>标签实现的,而script只能通过GET请求数据,不能POST

由于jsonp只能发GET请求,于是又有了CORS跨域
↓↓↓

CORS跨源AJAX请求

当使用ajax访问远程服务器时,请求失败,浏览器报No 'Access-Control-Allow-Origin' header
解决方案:后端程序员添加response.setHeader("Access-Control-Allow-Origin", "*");

CORS是跨源资源分享(Cross-Origin Resource Sharing)的缩写。它是W3C标准,是跨域AJAX请求的根本解决方法。
CORS允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
相比JSONP只能发GET请求,CORS允许任何类型的请求。

1
2
3
后端程序员加上这句响应头:
response.setHeader('Access-Control-Allow-Origin', 'http://stage.com:8000')
告诉浏览器,http://stage.com:8000可以向我方服务器发送ajax请求

或者前端程序员设置将ajax请求中的dataType属性设置为“jsonp”,jsonp是专门用来解决跨域访问而诞生的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$(function($){
var url = 'http://*****/index';
$.ajax(url, {
data: {
'cityname': '成都'
},
dataType: 'jsonp',
crossDomain: true,
success: function(data) {
if(data && data.resultcode == '200'){
console.log(data.result.today);
}
}
});

chrome调试

在用submit提交数据时,页面会刷新,因此:chrome开发者工具 → Network → Network → 点击preserve log(页面刷新时不清楚日志)

-------------本文结束感谢您的阅读-------------