目录
前言:
在前后端交互的过程中,有很多数据请求的方式,例如AJAX、Fetch、axios等等,下面就一一来简单列举一下。
我们先来看一下URL的两种的形式:
- 传统的URL格式如下:
scheme://host:port/path?query#fragment
其中:
scheme: 表示协议,如Http, Https, Ftp等;
host: 表示所访问资源所在的主机名:如:www.baidu.com;
port: 表示端口号,默认为80;
path: 表示所访问的资源在目标主机上的储存路径;
query: 表示查询条件;
fragment:表示锚点(哈希),用于定位页面的某个位置。
例如: http://www.baidu.com/search?words=Baidu
- restful形式的URL
(1)HTTP的请求方式:
- GET 查询
- POST 添加
- PUT 修改
- DELETE 删除
(2)符合规则的URL:(提交方式不同)
http://www.hello.com/books GET
http://www.hello.com/books POST
http://www.hello.com/books/123 PUT(对id为123的数据进行修改)
http://www.hello.com/books/123 DELETE(对id为123的数据进行删除)
1. AJAX
1.1 简介
AJAX 是 Asynchronous JavaScript and XML 的缩写,指的是通过 JavaScript 的异步通信,从服务器获取 XML 文档从中提取数据,再更新当前网页的对应部分,而不用刷新整个网页。
1.2 特点
- 优点
- 不需要插件支持(一般浏览器且默认开启 JavaScript 即可)
- 用户体验极佳(不刷新页面即可获取可更新的数据)
- 提升 Web 程序的性能(在传递数据方面做到按需发送,不必整体提交)
- 减轻服务器和带宽的负担(将服务器的一些操作转移到客户端)
- 缺点
- 前进、后退的功能被破坏(因为 AJAX 永远在当前页,不会记录前后页面)
- 搜索引擎的支持度不够(因为搜索引擎爬虫还不能理解 JS 引起变化数据的内容)
1.3 常见状态码
100 ~ 199 表示连接继续
200 ~ 299 表示各种意义上的成功
300 ~ 399 表示重定向
400 ~ 499 表示各种客户端错误
500 ~ 599
1.4 使用方法
AJAX 包括以下几个步骤:
- 创建XMLHttpRequest对象,也就是创建一个异步调用对象
- 创建一个新的HTTP请求,并指定其请求的方法、URL及验证信息
- 设置响应 HTTP 请求状态变化的函数
- 发送 HTTP 请求
- 获取异步调用返回的数据
- 使用 JavaScript 和 DOM 实现局部刷新
//原生AJAx
var request = new XMLHttpRequest(); // 新建XMLHttpRequest对象;
request.onreadystatechange = function () { // 状态发生变化时,函数被回调;
if (request.readyState === 4) { // 成功完成
// 判断响应结果:
if (request.status === 200) {
// 成功,通过responseText拿到响应的文本:
} else {
// 失败,根据响应码判断失败原因:
}
} else {
// HTTP请求还在继续...
}
}
// 发送请求:
request.open("POST","/skill-ajax/a/login",true);
request.setRequestHeader("Content-type","application/x-www-form-urlencoded");
request.send();
alert('请求已发送,请等待响应...');
// readyState值说明
// 0,初始化,XHR对象已经创建,还未执行open
// 1,载入,已经调用open方法,但是还没发送请求
// 2,载入完成,请求已经发送完成
// 3,交互,可以接收到部分数据
// status值说明
// 200:成功
// 404:没有发现文件、查询或URl
// 500:服务器产生内部错误
使用jQuery进行AJAX请求:
//jQuery中的AJAX
$.ajax({
method: 'GET', // 1.9.0本版前用'type'
url: url,
data: data,
dataType: dataType,
success: function() {
console.log('执行成功');
},
error: function() {
console.log('执行出错');
}
})
使用jQuery进行AJAX请求时它具有以下特点:
(1)优点:
- 对原生XHR的封装,做了兼容处理,简化了使用
- 增加了对JSONP的支持,可以简单处理部分跨域
(2)缺点:
- 如果有多个请求,并且有依赖关系的话,容易形成回调地狱
- 本身是针对MVC的编程,不符合现在前端MVVM的浪潮
- ajax是jQuery中的一个方法。如果只是要使用ajax却要引入整个jQuery,很不合理
1.5 使用Promise封装AJAX
这里不多做介绍,之前写了一篇相关文章:利用Promise封装Ajax中get和post方法
2. Fetch
2.1 Fetch简介
Fetch是基于Promise实现的,支持 async/await,它有更加简单的数据获取方式,功能更加强大、更灵活,可以看做是xhr的升级版。
// 原生XHR
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText) // 从服务器获取数据
}
}
xhr.send()
// fetch
fetch(url)
.then(response => {
return response.json();
})
.then(data => console.log(data)) // 这里得到的才是真正的数据
.catch(error => console.log(error))
2.2 常用参数
常用的参数配置:
(1)method
(String): HTTP请求方法,默认为GET (GET、POST、PUT、DELETE)
(2)body
(String): HTTP的请求参数
(3)headers
(Object): HTTP的请求头,默认为{}
2.3 基本用法
- GET 请求方式
//使用普通URL进行传递参数
fetch('/abc?id=123')
.then(response => {
return response.json();
})
.then(data => console.log(data))
.catch(error => console.log(error))
// 使用restful形式进行传参
fetch('/abc/123',{
method:'get'
}).then(response => {
return response.json();
}).then(data => console.log(data))
.catch(error => console.log(error))
- DELETE请求方式
delete请求方式和get方式类似:
//使用普通URL进行传递参数
fetch('/abc?id=123',{
method:'delete'
}).then(response => {
return response.json();
}).then(data => console.log(data))
.catch(error => console.log(error))
// 使用restful形式进行传参
fetch('/abc/123',{
method:'delete'
}).then(response => {
return response.json();
}).then(data => console.log(data))
.catch(error => console.log(error))
- POST请求方式
//以普通参数形式请求
fetch('/abc',{
method:'post',
body:'uname=zhangsan&psw=123',
headers:{
'Content-Type' : 'application/X-www-form-urlencoded'
}
}).then(response => {
return response.json();
}).then(data => console.log(data))
.catch(error => console.log(error))
// 以json格式进行请求
fetch('/abc',{
method:'post',
body:JSON.stringify({
uname:'zhangsan',
psw:'123'
})
headers:{
'Content-Type' : 'application/json'
}
}).then(response => {
return response.json();
}).then(data => console.log(data))
.catch(error => console.log(error))
- PUT请求方式
put请求方式和post类似:
//以普通参数形式请求
fetch('/abc/123',{ //123要修改数据的id
method:'put',
body:'uname=zhangsan&psw=123',
headers:{
'Content-Type' : 'application/X-www-form-urlencoded'
}
}).then(response => {
return response.json();
}).then(data => console.log(data))
.catch(error => console.log(error))
// 以json格式进行请求
fetch('/abc/123',{
method:'put',
body:JSON.stringify({
uname:'zhangsan',
psw:'123'
})
headers:{
'Content-Type' : 'application/json'
}
}).then(response => {
return response.json();
}).then(data => console.log(data))
.catch(error => console.log(error))
2.4 响应结果
Fetch响应数据的格式主要有以下两种:
-
text()
:将返回体处理成字符串类型 -
json()
:返回结果和JSON.parse
(responseText)一样
我们上面使用的是json()
格式,如果想用text()
格式,直接替换即可。
2.5 特点
(1)优点:
在配置中,添加mode:'no-cors'
就可以跨域了
fetch('/users.json', {
method: 'post',
mode: 'no-cors',
data: {}
}).then(function() { /* handle response */ });
(2)缺点:
- fetch只对网络请求报错,对400,500都当做成功的请求,需要封装去处理
- fetch默认不会带cookie,需要添加配置项。
- fetch不支持abort,不支持超时控制,使用setTimeout及Promise.reject的实现超时控制并不能阻止请求过程继续在后台运行,造成了流量的浪费。
- fetch没有办法原生监测请求的进度,而XHR可以。
3. axios
3.1 axios简介
axios是一个基于promise
的HTTP库,可以用在浏览器和 node.js
中。它本质也是对原生XMLHttpRequest
的封装,只不过它是Promise
的实现版本,符合最新的ES规范。
Vue作者尤雨溪推荐使用axios进行数据请求。
axios具有以下特点:
- 支持浏览器和 node.js
- 支持 promise
- 能拦截请求和响应
- 自动转换JSON数据
- 提供了并发请求的接口
3.2 基本用法
- GET请求和DELETE请求
get请求和delete请求的用法类似,下面只写get请求:
//通过传统的URL地址传递参数
axios.get('/user?id=12345')
.then(function (response) {
console.log(response); // 这是返回的一个封装好的对象
console.log(response.data); // 这才是后台响应的真正的数据
})
.catch(function (error) {
console.log(error);
});
//通过restful形式的URL进行传参
axios.get('/user/id=12345')
.then(function (response) {
console.log(response);
console.log(response.data);
})
.catch(function (error) {
console.log(error);
});
//通过params对象传递参数
axios.get('/user', {
params: {
ID: 12345
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
- POST请求和PUT请求
post和put类似,这里只列举post请求方式:
// 通过默认选项传参(默认传递的是json形式的数据)
axios.post('/user', {
uname:'zhangsan',
psw:'123'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
//通过URLSearchParams传递参数(application/x-www-form-urlencoded)
const params = new URLSeardhParams();
params . append('uname', 'zhangsan');
params . append ('psw', '123');
axios.post('/user', params)
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
- 并发请求
function getUserAccount(){
return axios.get('/user/12345');
}
function getUserPermissions(){
return axios.get('/user/12345/permissions');
}
axios.all([getUserAccount(),getUserPermissions()])
.then(axios.spread(function(acct,perms){
//当这两个请求都完成的时候会触发这个函数,两个参数分别代表返回的结果
}))
3.3 响应结果
我们上文中只说了响应的数据response.data
,响应结果中还有以下主要属性:
-
data
: 实际响应回来的数据 -
headers
: 响应头信息 -
status
: 响应状态码 -
statusText
: 响应状态信息
3.4 全局配置
在发送请求之前,我们可以对axios请求设置全局配置:
// 超时时间
axios.defaults.timeout = 3000;
//设置默认地址,配置请求的基准URL地址,在请求时就可以不写这一部分
axios.defaults.baseURL =http://www.baidu.com';
// 设置请求头
axios.defaults.headers[ 'mytoken'] = 'helloworld'
3.5 拦截器
- 请求拦截器
请求拦截器的作用是在发出请求之前设置一些信息:
axios.interceptors.request.use(function(config){
//在请求发出之前进行信息设置
config.headers.mytoken = 'helloworld' // 和全局配置设置请求头效果一样,但是更加灵活
return config;
},function(error){
// 处理响应的错误信息
console.log(error);
});
- 响应拦截器
响应拦截器的作用是在获取数据之前对数据进行一些加工处理:
axios.interceptors.response.use(function(response){
//对返回的数据进行处理
var data = response.data;
return data;
},function(error){
//处理响应的错误信息
console.log(error);
});
4. async / await
async / await
方法是ES7中引入的新语法,可以更加便捷的进行异步操作。其中:
-
async
关键字用于函数上(async
函数的返回值是Promise实例对象) -
await
关键字用于async函数当中(await
可以得到异步的结果)
async function queryData (id) {
const ret = await axios.get('/data'); //可以直接得到调用结果,不需要再使用then
return ret;
}
// 因为上一步返回的Promise对象,所以通过调用then,可以直接获得上面获取到的数据
queryData.then (ret=> {
console.log (ret)
})
使用async / await
处理多个异步请求:
对于多个异步请求 ,我们只要在async函数中按照顺序处理异步任务即可:
async function queryData(id) {
const info = await axios. get('/async1') ;
const ret = await axios . get ( 'async2?info='+info.data) ;
return ret;
}
queryData.then (ret=>{
console.log (ret)
})
这大概就是这些请求方式的简单介绍以及基本使用方法。【完】