- 什么是Ajax跨域?
- 什么是同源策略?
- 怎么解决跨域?
- JSONP
- CORS
什么是Ajax跨域?
同源策略是跨域问题产生的根本原因。并且跨域是浏览器行为,也就是说服务器发送了请求,客户端也接收到了只是浏览器拒绝接收服务器传回的数据。
什么是同源策略?
同源策略是指在Web浏览器中,允许某个网页脚本访问另一个网页的数据,但前提是这两个网页必须有相同的协议、域名和端口,一旦两个网站满足上述条件,这两个网站就被认定为具有相同来源。
怎样解决跨域?
本文只探究两个方法:JSONP和CORS。
JSONP:
JSONP解决跨域,主要因为<script>
标签具有跨域能力。因此只是“绕过”了跨域,并没有根本解决问题。
JSONP跨域实现:
function cb(result) {
console.log(result)
}
btn.onclick = function () {
let sc = document.createElement("script");
sc.src = "http://suggest.taobao.com/sug?code=utf-8&q=电脑&callback=cb"
document.body.appendChild(sc)
}
实现原理主要是创建了script
标签,改变src
属性值。并且请求方式必须是GET,必须使用和后端相同的回调函数名获取后端数据。
JSONP跨域优缺点:
优点:
- 兼容性好
缺点:
- 只能使用GET请求
- 后端必须拥有回调函数且函数名和前端相同
- 错误处理机制并不完善
CORS:
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
CORS解决跨域分为简单请求和复杂请求。
区分CORS简单请求:
- 请求方式:
-
HEAD
、 -
GET
、 POST
-
- HTTP头信息:
-
Accept
、 -
Accept-Language
、 -
Content-Language
、 -
Last-Event-ID
、 Content-Type:application/x-www-form-urlencoded或multipart/form-data或text/plain
-
只要满足上述条件之一就是简单请求。
简单请求:
在头信息中添加Origin
字段。
-
Access-Control-Allow-Origin
必须填写,具体值或*
-
Access-Control-Allow-Credentials
可选,是否允许发送cookie
,设置为true
表示默认在请求之中。 -
Access-Control-Expose-Headers
:可选,拿到其他字段。
Fetch解决跨域:
主要方法也是设置请求头实现跨域(Access-Control-Allow-Origin
)。
fetch
返回一个Promise
对象,因此需要使用then
取得返回结果。
//前端使用fetch关键字
fetch('http://localhost:8090/api/data?cb=getData', { //请求地址
method: 'GET',//请求方式
mode: 'cors' //请求模式(跨域)
}).then(res => {
return res.json();
}).then(res => {
console.log(res.data);
})
//后端设置响应头
res.writeHead(200,{
'Access-Control-Allow-Origin':'*'
})
当然也可以将回调函数改为async/await
形式:
async function getData() {
try {
let response = await fetch('http://localhost:8090/api/', {
method: 'POST',
body:JSON.stringify({name:'www'}),
mode: "cors"
});
return await response.json();
} catch (error) {
console.log('Request Failed', error);
}
}
async function data() {
let data = await getData();
console.log(data.data);
}
data();
复杂请求;
在实际请求钱,增加一次HTTP查询请求。
在简单请求中我们只需要设置Access-Control-Allow-Origin
字段即可。但在复杂请求中我们需要设置不同请求头。
CORS优缺点:
优点:
- 支持所有类型的HTTP请求
- 可以通过onerror监听错误
缺点:
- 兼容性不好,IE10以下不支持