引言
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时可以无视同源策略
如以上代码所示,当我们在加载以上类型的 图片、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以及跨域的一些信息就讲到这里啦!如有疑问欢迎评论区评论或私信我交流~
关注公众号 星期一研究室 ,不定期分享学习干货
如果这篇文章对你有用,记得点个赞加个关注再走哦~