您的位置:首页 > 理论基础 > 计算机网络

fetch与ajax(XMLHttpRequest)相比

2018-04-01 19:49 330 查看

前言

ES6中新增了一种HTTP数据请求的方式,就是
fetch
,它和
XMLHttpRequest
有许多相似的功能,但是相比
XMLHttpRequest
,
fetch
被设计成更具可扩展性和高效性。江湖上一直流传着 “传统ajax已死,fetch永生”的说法,下面详细说下二者

详情

1.
XMLHttpRequest
请求数据

var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.responseType = 'json';

xhr.onload = function() {
console.log(xhr.response);
};

xhr.onerror = function() {
console.log("Oops, error");
};

xhr.send();


2.
fetch
请求数据

fetch(url)
.then(response => response.json())
.then(data => console.log(data))
.catch(e => console.log("Oops, error", e))


两段代码相比之下,
fetch
更为简洁,而且
fetch
请求属于
promise
结构,直接
.then()
方法处理回调数据,当出错时,会执行
catch
方法,而且
promise
避免了回调金字塔的问题。

3.
fetch
浏览器支持情况

目前谷歌浏览器对fetch的支持良好,具体支持情况如下图



当然,你也可以去这里查看can i use

4.
fetch
请求的四种方式

get请求

fetch(url)
.then(response => response.json())
.then(data => console.log(data))
.catch(e => console.log("Oops, error", e))


如果需要传递参数,需要拼接在
url


后面这里的调用的第一个
then
函数里面,返回结果是一个可读流形式



如果请求的是json数据,需要调用
response.json()
(这里的
response
是传递的参数)将可读流解析为json数据,在下一个
then
方法中,就可以得到想要的json数据了



同理,如果请求的txt文本数据,则需要调用
response.text()
来解析…更多调用的解析方法如下

response.arrayBuffer()
读取 Response对象并且将它设置为已读(因为Responses对象被设置为了 stream 的方式,所以它们只能被读取一次) ,并返回一个被解析为ArrayBuffer格式的promise对象

response.blob()
读取 Response对象并且将它设置为已读(因为Responses对象被设置为了 stream 的方式,所以它们只能被读取一次) ,并返回一个被解析为Blob格式的promise对象

response.formData()
读取Response对象并且将它设置为已读(因为Responses对象被设置为了 stream 的方式,所以它们只能被读取一次) ,并返回一个被解析为FormData格式的promise对象

response.json()
读取 Response对象并且将它设置为已读(因为Responses对象被设置为了 stream 的方式,所以它们只能被读取一次) ,并返回一个被解析为JSON格式的promise对象

response.text()
读取 Response对象并且将它设置为已读(因为Responses对象被设置为了 stream 的方式,所以它们只能被读取一次) ,并返回一个被解析为USVString格式的promise对象


对于
catch
方法,只有报程序出错的时候才会执行。

post请求

fetch(url,{
method:'POST',
headers:{
'Content-type':'application/json'// 设置请求头数据类型
},
body:data
})
.then(res=>res.json())
.then(data=>console.log(data))


method
:设置设置请求的方式,默认是
get
,另外还有
PUT
DELETE


headers
:设置请求头信息,当然,这里面还可以设置别的信息,比如:

var u = new URLSearchParams();
u.append('method', 'flickr.interestingness.getList');
u.append('api_key', '<insert api key here>');
u.append('format', 'json');
u.append('nojsoncallback', '1');

fetch(url,{
method:'POST',
headers:u,
body:data
})
.then(res=>res.json())
.then(data=>console.log(data))


另外,
fetch
可以在
header
中设置
CORS
跨域

u.append("Access-Control-Allow-Origin", "*");
u.append("Access-Control-Allow-Headers", "X-Requested-With");
u.append("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
u.append("X-Powered-By",' 3.2.1')


如果服务器不支持
CORS
fetch
提供了三种模式,其中
no-cors
可以继续访问服务器

fetch
mode
配置项有3个值,如下:

same-origin
:该模式是不允许跨域的,它需要遵守同源策略,否则浏览器会返回一个error告知不能跨域;其对应的response type为basic。

cors
: 该模式支持跨域请求,顾名思义它是以
CORS
的形式跨域;当然该模式也可以同域请求不需要后端额外的
CORS
支持;其对应的
response type
cors


no-cors
: 该模式用于跨域请求但是服务器不带
CORS
响应头,也就是服务端不支持
CORS
;这也是
fetch
的特殊跨域请求方式;其对应的
response type
opaque


针对跨域请求,cors模式是常见跨域请求实现,但是fetch自带的no-cors跨域请求模式则较为陌生,该模式有一个比较明显的特点:

该模式允许浏览器发送本次跨域请求,但是不能访问响应返回的内容,这也是其response type为opaque透明的原因,如下图:



呃,感觉这样虽然解决能跨域问题,但是请求不到任何数据,还是没有卵用…

注意: cors 支持 三种
content-type
不支持
application/json


application/x-www-form-urlencoded

multipart/form-data

text/plain

body
:需要传递的参数

fetch
请求默认是不会携带
cookie
信息,如果想要携带,需要在手动设置

fetch(url, {
method: 'POST',
headers:{
'Content-type':'application/json'// 设置请求头数据类型
},
credentials: "include"
})


credentials: "include"
设置请求头携带
cookie
信息

put请求

fetch(url,{
method:'PUT',
headers:{
'Content-type':'application/json'// 设置请求头数据类型
},
body:data
})
.then(res=>res.json())
.then(data=>console.log(data))


delete请求

fetch(url,{
method:'DELETE',
headers:{
'Content-type':'application/json'// 设置请求头数据类型
},
body:data
})
.then(res=>res.json())
.then(data=>console.log(data))


其实,
post
,
put
,
delete
,这三个请求代码上差不多,只是method中对应不同的请求方法不同而已。

如下是自己封装的
fetch
的API代码

HTML页面

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>

<script src="easyhttp.js"></script>
<script src="app.js"></script>
</body>
</html>


app.js

const url = 'http://jsonplaceholder.typicode.com/users';

let easyHttp = new EasyHttp;

// 请求数据
easyHttp.get(url)
.then(res=>console.log(res))
.catch(err=>console.log(err))

// 发送数据
const data = {
name:"Henry",
username:"露丝",
email:"lusi@qq.com"
};
// easyHttp.post(url,data)
//         .then(res=>console.log(res))
//         .catch(err=>console.log(err))

// 修改数据
// easyHttp.put(url+'/10',data)
//         .then(res=>console.log(res))
//         .catch(err=>console.log(err))

easyHttp.delete(url+'/2',data)
.then(res=>console.log(res))
.catch(err=>console.log(err))


easyhttp.js

/**
* fetch 增删改查 的API封装
*/

class EasyHttp{
//  get 请求
get(url){
return new Promise((resolve,reject)=>{
fetch(url)
.then(res=>res.json())
.then(data=>resolve(data))
.catch(err=>reject(err))
})
}

// post 请求

post(url,data){
return new Promise((resolve,reject)=>{
fetch(url,{
method:'POST',
headers:{
'Content-type':'application/json'// 设置请求头数据类型
},
body:data
})
.then(res=>res.json())
.then(data=>resolve(data))
.then(err=>reject(err))
})
}

// put 请求修改数据
put(url,data){
return new Promise((resolve,reject)=>{
fetch(url,{
method:'PUT',
headers:{
'Content-type':'application/json'// 设置请求头数据类型
},
body:data
})
.then(res=>res.json())
.then(data=>resolve(data))
.then(err=>reject(err))
})
}

// delete 删除数据
delete(url,data){
return new Promise((resolve,reject)=>{
fetch(url,{
method:'DELETE',
headers:{
'Content-type':'application/json'// 设置请求头数据类型
},
body:data
})
.then(res=>res.json())
.then(data=>'删除数据成功。。。')
.then(err=>reject(err))
})
}

}


源码地址戳一下

最后总结

fetch
XMLHttpRequest
相比,主要有以下优点:

语法简洁,更加语义化

基于标准 Promise 实现,支持 async/await

同构方便,使用 isomorphic-fetch

参考文章

MDN Fetch API

ECMAScript 6 入门

Fetch相比Ajax有什么优势?

【fetch跨域请求】cors

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息