HTTP数据请求的方式:fetch与ajax(XMLHttpRequest)与axios

 传统 Ajax 指的是 XMLHttpRequest(XHR),最早出现的发送后端请求技术,核心使用XMLHttpRequest对象,多个请求之间如果有先后关系的话,就会出现回调地狱。JQuery ajax 是对原生XHR的封装,除此以外还增添了对JSONP的支持.

1.本身是针对MVC的编程,不符合现在前端MVVM的浪潮
2.基于原生的XHR开发,XHR本身的架构不清晰。
3.JQuery整个项目太大,单纯使用ajax却要引入整个JQuery非常的不合理(采取个性化打包的方案又不能享受CDN服务)
4.不符合关注分离(Separation of Concerns)的原则
5.配置和调用方式非常混乱,而且基于事件的异步模型不友好。

MVVM(Model-View-ViewModel), 源自于经典的 Model–View–Controller(MVC)模式。MVVM 的出现促进了 GUI 前端开发与后端业务逻辑的分离,极大地提高了前端开发效率。MVVM 的核心是 ViewModel 层,它就像是一个中转站(value converter),负责转换 Model 中的数据对象来让数据变得更容易管理和使用,该层向上与视图层进行双向数据绑定,向下与 Model 层通过接口请求进行数据交互,起呈上启下作用。View 层展现的不是 Model 层的数据,而是 ViewModel 的数据,由 ViewModel 负责与 Model 层交互,这就完全解耦了 View 层和 Model 层,这个解耦是至关重要的,它是前后端分离方案实施的最重要一环。

Vue2.0之后,尤雨溪推荐大家用axios替换JQuery ajax,想必让axios进入了很多人的目光中。
axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范,它本身具有以下特征:
  1.从浏览器中创建 XMLHttpRequest
  2.支持 Promise API
  3.客户端支持防止CSRF
  4.提供了一些并发请求的接口(重要,方便了很多的操作)
  5.从 node.js 创建 http 请求
  6.拦截请求和响应
  7.转换请求和响应数据
  8.取消请求
  9.自动转换JSON数据
  PS:防止CSRF:就是让你的每个请求都带一个从cookie中拿到的key, 根据浏览器同源策略,假冒的网站是拿不到你cookie中得key的,这样,后台就可以轻松辨别出这个请求是否是用户在假冒网站上的误导输入,从而采取正确的策略。

fetch号称是AJAX的替代品,是在ES6出现的,使用了ES6中的promise对象。Fetch是基于promise设计的。Fetch的代码结构比起ajax简单多了,参数有点像jQuery ajax。但是,一定记住fetch不是ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象。
fetch的优点:
1.符合关注分离,没有将输入、输出和用事件来跟踪的状态混杂在一个对象里
2.更好更方便的写法,fetch的优势主要优势就是:

1.  语法简洁,更加语义化
2.  基于标准 Promise 实现,支持 async/await
3.  同构方便,使用 [isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch)
4.fetch请求默认是不带cookie的,需要设置fetch(URL,{credentials:’include’})。
5.更加底层,提供的API丰富(request, response)
6.脱离了XHR,是ES规范里新的实现方式
7.fetch只对网络请求报错,对400,500都当做成功的请求,服务器返回 400,500 错误码时并不会 reject,只有网络错误这些导致请求不能完成时,fetch 才会被 reject。
1)fetch默认不会带cookie,需要添加配置项: fetch(url, {credentials: 'include'})
2)fetch不支持abort,不支持超时控制,使用setTimeout及Promise.reject的实现的超时控制并不能阻止请求过程继续在后台运行,造成了流量的浪费
3)fetch没有办法原生监测请求的进度,而XHR可以



首先.ajax

是XMLHTTPRequest的一个实例;
只有当状态为200或者304时才会请求成功;

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避免了回调金字塔的问题

 

.fetch请求的四种方式

get请求

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

如果需要传递参数,需要拼接在url
后面这里的调用的第一个then函数里面,返回结果是一个可读流形式

clipboard.png

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

clipboard.png

同理,如果请求的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,另外还有PUTDELETE
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')  

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

fetchmode配置项有3个值,如下:

  • same-origin:该模式是不允许跨域的,它需要遵守同源策略,否则浏览器会返回一个error告知不能跨域;其对应的response type为basic。
  • cors: 该模式支持跨域请求,顾名思义它是以CORS的形式跨域;当然该模式也可以同域请求不需要后端额外的CORS支持;其对应的response typecors
  • no-cors: 该模式用于跨域请求但是服务器不带CORS响应头,也就是服务端不支持CORS;这也是fetch的特殊跨域请求方式;其对应的response typeopaque

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

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

clipboard.png

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

注意: 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))  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值