背景
前端的技术发展速度非常的快,异步请求也是其重要的体现之一,从最早的原生XHR,再到JqueryAjax的统治时代,再到近来,fetch、axios等技术也开始出现并大量投入使用。
原生Ajax
Ajax是指一种创建交互式网页应用的网页开发技术,并且可以做到无需重新加载整个网页的情况下,能够更新部分网页,也叫作局部更新。
XMLHttpRequest 对象
使用ajax发送请求是依靠于一个对象,叫XmlHttpRequest对象,通过这个对象我们可以从服务器获取到数据,然后再渲染到我们的页面上。现在几乎所有的浏览器都有这个对象,只有IE7以下的没有,而是通过ActiveXObject这个对象来创建的。XmlHttpRequest对象有一些常见的方法:
方法 |
描述 |
abort() |
停止当前请求 |
getAllResponseHeaders() |
把HTTP请求的所有响应首部作为键/值对返回 |
getResponseHeader(“header”) |
返回指定首部的串值 |
open(method,url) |
建立对服务器的调用,还有3个可选参数,是否异步、用户名、密码 |
send(content) |
向服务器发送请求 |
abort() |
停止当前请求 |
setRequestHeader(header, value) |
把指定首部设置为所提供的值。 |
ajax使用步骤
1.创建XmlHttpRequest对象
2.调用open方法设置基本请求信息
3.设置发送的数据,发送请求
4.注册监听的回调函数
5.拿到返回值,对页面进行更新
ajax的get/post请求
其实get和post的请求方式大致是相同的,下面分别是get和post的示例代码:
get
<script>
//步骤一:创建异步对象
var xhr = new XMLHttpRequest();
//步骤二:设置请求的基本参数
xhr.open('get','test.php');
//步骤三:发送请求
xhr.send();
//步骤四:注册onreadystatechange监听事件,只要状态改变就会调用
xhr.onreadystatechange = function () {
if (ajax.readyState == 4 && ajax.status == 200) {
//步骤五 如果能够进到这个判断 说明数据完美到手
console.log(ajax.responseText);//操作返回内容
}
}
</script>
post
<script>
//创建异步对象
var xhr = new XMLHttpRequest();
//设置请求基本信息,并加上请求头
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.open('post', 'test.php' );
//发送请求
xhr.send('name=Lan&age=18');
xhr.onreadystatechange = function () {
// 这步为判断服务器是否正确响应
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText);
}
};
</script>
onreadystatechange
这个监听函数是来监听readyState这个状态值得:
状态值 |
描述 |
0 |
请求还未初始化,还未调用open( ) |
1 |
请求已建立但未发送,还未调用send( ) |
2 |
接受原始响应数据,为解析做准备 |
3 |
正在解析数据,根据响应头部返回的MIME类型把数据转换成能通过responseText等形式存取的格式 |
4 |
响应完成,数据解析完成 |
ajax优缺点
优点 :
局部更新
原生支持,不需要任何插件
缺点 :
可能破坏浏览器后退功能
嵌套回调,难以处理
JqueryAjax
其实Jquery的ajax就是在原生的ajax的基础上进行了封装,其实没有太多好说的东西,不过加上了对 JSONP 的支持,附上例子:
<script>
var loginBtn = document.getElementsByTagName("button")[0];
loginBtn.onclick = function(){
ajax({
type:"post",
url:"test.php",
data:"name=lan&pwd=123456",
success:function(data){
console.log(data);
}
});
}
</script>
ajax方法里面需要传入一个对象参数,里面包括了一些常见的参数,其实jquery维护了这么多年了,ajax请求其实已经很方便了,如果非要说有什么缺点的话,就是依然对回调嵌套不方便,然后就是如果为了一个JqueryAjax就引入整个jquery,文件比较大,成本过高。(JQ1.5之后好像是支持了Promise写法)
Fetch
Fetch是ajax非常好的一个替代品,很有可能将来会完全代替ajax的地位。我们先来看下浏览器的支持情况:
我们可以看到IE浏览器完全不支持Fetch,并且移动端的很多浏览器也不支持Fetch,不过可以使用第三方的ployfill来获得支持。
Github.fetch
Fetch写法
不管是原生的Ajax还是Jquery封装的Ajax都有一个问题就在于回调地狱,fetch很友好的解决了这个问题,fetch大概长这个样子:
fetch(...).then(fun2)
.then(fun3)
.....
.catch(fun)
它给人一种同步的流程来书写非同步的操作,成功的解决了回调地狱的问题。Fetch能做到这一点,是因为Fetch API是基于Promise设计的。并且fetch调用非常简单,因为它是挂在BOM上的,属于全局的方法。
Fetch获取数据
我们使用Fetch来获取数据时,会返回给我们一个Pormise对象,我们简单看一下:
<script>
fetch("http://www.abc.cn/test")
.then(Response => {
console.log(Response);
})
</script>
输出如下:
OK就是true,status是200,我们可以看到这里面并没有我们想要的数据,其实数据都在body属性里面,是一种数据流的形式,一般服务器会给我们返回JSON数据的格式,我们可以调用response.json来转化下数据:
<script>
fetch("http://www.abc.cn/test")
.then(Response => Response.json())
.then(data => {
console.log(data);
})
</script>
处理之后,我们继续.then就可以拿到处理之后的数据了。所以这么来看的话通过Fetch来获取数据是非常简洁简单的。
Fetch发送数据
Fetch发送数据也非常的简单,API长这样:
fetch(url,options)
第二个参数会传入一个对象来配置请求的信息。下面先看一个例子:
<script>
fetch('http://www.mozotech.cn/bangbang/index/user/login', {
method: 'post',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams([["username", "Lan"],["password", "123456"]]).toString()
})
.then(res => {
console.log(res);
return res.text();
})
.then(data => {
console.log(data);
})
</script>
对传入的参数做个说明:
参数名 |
描述 |
method |
请求的方法,默认GET |
headers |
请求的头信息 |
body |
请求的内容主体 |
值得一提的是,fetch默认的post的header是Content-Type:text/plain;charset=UTF-8,不过通常我们的post请求是通过表单的形式提交的。所以我们需要把header修改为:Content-Type:application/x-www-form-urlencoded
Cookie传递
fetch发送请求时,不像XHR,因为它默认是不带上Cookie的,如果站点依赖于维护一个用户会话,可能导致未经认证的请求,所以我们需要手动的把Cookie带上,只需加上 credentials: 'include’即可:
<script>
fetch('https://www.abc.com/search', {
method: 'GET',
credentials: 'include' // 强制加入Cookie
})
.then((res)=>{
return res.text()
})
.then((res)=>{
console.log(res)
})
</script>
Fetch优缺点
优点:
解决回调地狱
使用起来更加简洁
缺点:
API 偏底层,需要封装
默认不带Cookie,需要手动添加
浏览器支持情况不是很友好,需要第三方的ployfill
Axios
axios的github地址
Vue2.0之后,axios开始受到更多的欢迎了。其实axios也是对原生XHR的一种封装,不过是Promise实现版本。
它是一个用于浏览器和 nodejs 的 HTTP 客户端,符合最新的ES规范。简单看下如何使用即可
<script>
axios({
method: 'post',
url: '/abc/login',
data: {
userName: 'Lan',
password: '123'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
</script>
感觉axios算是比较完美的一种方案了,几乎没有什么大的缺点。
同时发起多个请求:
axios的特点
支持浏览器和node.js
支持promise
能拦截请求和响应
能转换请求和响应数据
能取消请求
自动转换JSON数据
浏览器端支持防止CSRF(跨站请求伪造)
axios提问
原链接地址
- 如何将axios异步请求同步化处理?
//使用 asyns/await
async getHistoryData (data) {
try {
let res = await axios.get('/api/survey/list/', {
params: data
})
this.tableData = res.data.result
this.totalData = res.data.count
} catch (err) {
console.log(err)
alert('请求出错!')
}
}
- 为何官方推荐使用axios而不用vue-resource?
在Vue1.x中,官方推荐使用的ajax库是vue-resource。到了Vue2.x,官方(尤大)推荐的ajax库改为了Axios,按照说法是因为已有一个更完备的轮子,就不需要造一个新的。
-
你了解axios的原理吗?有看过它的源码吗?
Axios源码深度剖析
-
你有封装过axios吗?主要是封装哪方面的?
具体config配置参考
到具体页面中的应用:
-
如何中断(取消)axios的请求?
-
axios怎么解决跨域的问题?
-
如果 server 端是自己开发的,那么修改相关代码支持跨域即可。如果不是自己开发的,那么可以自己写个后端转发该请求,用代理的方式实现。
-
跨域这个行为是浏览器禁止(浏览器不允许当前页面的所在的源去请求另一个源的数据)的,但是服务端并不禁止
-
源指协议、端口、域名。只要这个3个中有一个不同就是跨域。 这里列举一个经典的列子:
协议跨域:
http://a.baidu.com访问https://a.baidu.com;
端口跨域:
http://a.baidu.com:8080访问http://a.baidu.com:80;
域名跨域:
http://a.baidu.com访问http://b.baidu.com;
- 关键字:Access-control-Allow-origin、跨域
- 几种解决跨域的方法
- A) 开发模式下,可以在config中配置proxyTable即可
- B) 服务端基于spring实现
- C) CORS:①即跨源资源共享,它定义了一种浏览器和服务器交互的方式来确定是否允许跨域请求。
②它是一个妥协,有更大的灵活性,但比起简单地允许所有这些的要求来说更加安全。③但是CORS也具有一定的风险性,比如请求中只能说明来自于一个特定的域但不能验证是否可信,而且也容易被第三方入侵。
④这里一般需要后端配合,开启cors。一般各种语言都有类似的包。比如NodeJS的koa2-cors
- D) Nginx代理proxy
-
请求头自动携带cookie时:config中配置withCredentials:true,否则为false【看到有人说:withCredentials为true的情况下,后端要设置Access-Control-Allow-Origin为你的源地址,例如http://localhost:8080,不能是*,而且还要设置header(‘Access-Control-Allow-Credentials:
true’)】
-
config中配置qs:避开ajax信使请求,并兼容Android?
import Qs from 'qs'
总结
其实有这么多种的请求方法和解决方案,总结一下:原生XHR几乎很少开发会用,JqueryAjax属于老当益壮的那种,虽然很老,但是很好用,Fetch是属于初生牛犊,还需要慢慢成长,axios就目前来说,算是非常好的了,无脑使用即可。
————————————————
版权声明:本文为CSDN博主「Lan.ZerGan」的原创文章,遵循CC 4.0 BY-SA版权协议
原文链接:https://blog.csdn.net/qq_36407875/article/details/84642060