引言
ajax对于前端来说是一个特别基础也特别实用的一个功能,基本上我们目前访问的很多网页都有用到 ajax
的功能。接下来开始讲解关于AJAX请求,以及关于跨域的一些内容。
正文
一、AJAX请求
Ajax
,即 Asynchronous Javascript And XML
(异步JavaScript和XML)。
在实现 Ajax
之前,我们先来了解下 XMLHttpRequest
。 XMLHttpRequest
是网页实现 AJAX
最主要的一个 API
。可能有很多同学知道 AJAX
,也用过 AJAX
,但是却不知道它是基于 XMLHttpRequest
来实现的。
那么接下来我们用 XMLHttpRequest
这个 API
来模拟一个 get
和 post
请求。
1、模拟get和post请求
(1)模拟get请求:
/**
* 使用xhr模拟实现GET请求
*/
const xhr = new XMLHttpRequest();
xhr.open('GET', '/test.json', true); //false表示同步请求,true表示异步请求
xhr.onreadystatechange = function () {
// 这里的函数异步执行
if(xhr.readyState === 4){
if(xhr.status === 200){
// console.log(
// JSON.parse(xhr.responseText)
// );
alert(xhr.responseText);
}
}
}
// 因为是get请求,所以只要发送null就好
xhr.send(null);
(2)模拟post请求:
/**
* 使用xhr模拟实现post请求
*/
const xhr = new XMLHttpRequest();
//模拟请求一个登录接口
xhr.open('POST', '/login', true); //false表示同步请求,true表示异步请求
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status === 200){
console.log(
JSON.parse(xhr.responseText)
);
alert(xhr.responseText);
}else{
console.log('其他情况');
}
}
}
const postData = {
userName: 'zhangsan',
password: 'xxx'
}
xhr.send(JSON.stringify(postData));
2、封装一个简易的AJAX
function ajax(url){
const p = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function(){
//状态码的解析详细看第二点
if(xhr.readyState === 4){
if(xhr.status === 200){
resolve(
JSON.parse(xhr.responseText)
);
}else if(xhr.status === 404){
reject(new Error('404 not found'));
}
}
}
xhr.send(null);
});
return p;
}
const url = '你的json数据路径';
ajax(url)
.then(res => console.log(res))
.catch(err => console.error(err));
二、状态码
看完上面的模拟过程之后,我们来讲解其中的几个知识点。
1、xhr.readyState
readyState状态值 | readyState含义 |
---|---|
0 | (未初始化)- 还没有调用send()方法 |
1 | (载入)- 已调用send()方法,正坐在发送请求 |
2 | (载入完成)- send()方法执行完成,已经接收到全部响应内容 |
3 | (交互)- 正在解析响应内容 |
4 | (完成)响应内容解析完成,可以在客户端调用 |
2、xhr.status
status状态值 | status含义 |
---|---|
2xx | 表示成功处理请求,如200 |
3xx | 需要重定向,浏览器直接跳转,如301 302 304 |
4xx | 客户端请求错误,如404 403 |
5xx | 服务器端错误 |
三、跨域
1、同源策略
(1)同源策略是什么
同源策略是浏览器自带的一种安全策略,它是指网址中的协议、域名、端口三个都相同时才能互相访问,即若协议、域名、端口有一个不相同时,浏览器禁止页面加载或执行与自身不同域的脚本。
(2)为什么浏览器会有同源策略?
因为如果没有同源策略,别人就可以轻松的获取我们网站的 cookie
信息,或是对网页进行 DOM
操作;
这是一件非常恐怖的事情,尤其是 cookie
信息,它里面存在着 sessionID
,这是与服务端的 session
会话的重要凭证,如果被别人得到了 cookie
,有很大可能会造成数据被盗取等后果。
(3)同源策略限制内容有哪些?
- 存储在浏览器中的数据,如
localStroage
、Cookie
和IndexedDB
不能通过脚本跨域访问; - 不能通过脚本操作不同域下的
DOM
; - 不能通过
ajax
请求不同域的数据。
(4)加载图片、js和css时可以无视同源策略
<img src = 跨域的图片地址 />
<link href = 跨域的css地址/>
<script src = 跨域的js地址></script>
如以上代码所示,当我们在加载以上类型的 图片、css和js
时,可以无视同源策略。因为像 图片、css文件和js文件
一般可使用 cdn
来进行缓存,而 cdn
一般是外域。同时, js
文件也可以通过 JSONP
来实现跨域。
2、跨域解决方案
(1)跨域是什么
- 所有的跨域,都必须经过
server
端允许和配合; - 未经
server
端允许就实现跨域,说明浏览器有漏洞,是一种危险信号。
(2)解决跨域的方式
1)JSONP(客户端操作)
① JSONP的原理
JSONP
(JSON with Padding)是数据格式 JSON
的一种“使用模式”,可以让网页从别的网域要数据。
根据 XmlHttpRequest
对象受到同源策略的影响,而利用
用 JSONP
抓到的数据并不是 JSON
,而是任意的 JavaScript
,用 JavaScript
解释器运行而不是用 JSON
解析器解析。
所以,通过 Chrome
查看所有 JSONP
发送的 Get
请求都是 js
类型,而非 XHR
。
② JSONP包含两部分:回调函数和数据
回调函数是当响应到来时要放在当前页面被调用的函数。
数据就是传入回调函数中的 json
数据,也就是回调函数的参数了。
function handleResponse(response){
console.log('The responsed data is: '+response.data);
}
var script = document.createElement('script');
script.src = 'http://www.baidu.com/json/?callback=handleResponse';
document.body.insertBefore(script, document.body.firstChild);
/*handleResonse({"data": "zhe"})*/
//原理如下:
//当我们通过script标签请求时
//后台就会根据相应的参数(json,handleResponse)
//来生成相应的json数据(handleResponse({"data": "zhe"}))
//最后这个返回的json数据(代码)就会被放在当前js文件中被执行
//至此跨域通信完成
③ 缺点:
- 只能使用Get请求。
- 不能注册success、error等事件监听函数,不能很容易的确定
JSONP
请求是否失败。 JSONP
是从其他域中加载代码执行,容易受到跨站请求伪造的攻击,其安全性无法确保。
2)CORS(服务器操作)
① cors的原理
CORS
(Cross-Origin Resource Sharing),即跨域资源共享,是一种浏览器技术的规范,提供了 Web
服务从不同域传来沙盒脚本的方法,以避开浏览器的同源策略,确保安全的跨域数据传输。现代浏览器使用 CORS
在 API
容器如 XMLHttpRequest
来减少 HTTP
请求的风险来源。与 JSONP
不同,CORS
除了 GET
要求方法以外也支持其他的 HTTP
要求。
② cors
的跨域方法一般是服务端进行操作,服务端需要设置以下 http header
:
//设置允许跨域的域名称,不建议直接写“*”
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");
//填写允许跨域的http请求方法
//当 method = OPTIONS 时, 属于预检(复杂请求), 当为预检时, 可以直接返回空响应体, 对应的 http 状态码为 204
response.setHeader("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
//设置需要支持的跨域请求头,如果设置为*,表明服务器支持所有头信息字段;也可设置为X-Request-With和Content-Type
response.setHeader("Access-Control-Allow-Headers", "X-Request-With, Content-Type");
// 服务器收到请求以后,检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。
//表示具体请求中的媒体类型信息
response.setHeader("Content-Type", "application/json;charset=utf-8");
//设置预检结果的缓存, 单位(秒)
response.setHeader("Access-Control-Max-Age", 86400);
/*如果需要支持 cookies,
*Access-Control-Allow-Origin 不能设置为 *,
*并且 Access-Control-Allow-Credentials 需要设置为 true
*(注意前端请求需要设置 withCredentials = true)
*/
response.setHeader("Access-Control-Allow-Credentials", "false");
结束语
以上文章浅谈了 ajax
以及常用的跨域方案,没有深究到很细节层面的内容。希望对大家有帮助!
关于Ajax以及跨域的一些信息就讲到这里啦!如有疑问欢迎评论区评论或私信我交流~
关注公众号 星期一研究室 ,不定期分享学习干货
如果这篇文章对你有用,记得点个赞加个关注再走哦~