axios、fetch 和 ajax 等的区别详解

  主体内容来自: https://www.jianshu.com/p/8bc48f8fde75前端

  axios、fetch 和 ajax的区别 在网络上存在不少文章。我的现针对本身的状况,来从新整理一份,便于本身记忆和理解。内容参考了网络上的众多文章。node

 

XMLHttpRequest

  浏览器经过XMLHttpRequest 对象进行 http 通讯。ios

  传统Ajax 指的是 XMLHttpRequest(XHR),最先出现的向后端发送请求的技术,隶属于原始 js 中, 核心使用 XMLHttpRequest 对象,多个请求之间若是有前后关系的话,就会出现 回调地狱git

 

  推荐一篇有关 XMLHttpRequest 的文章:XMLHttpRequest ——必知必会
github

 

  经常使用语法:ajax

  一个简单的 http 请求编程

let xhr = new XMLHttpRequest();
xhr.open('GET', '/url', true);
xhr.send();

    

  一个稍微完整的 http 请求json

let xhr = new XMLHttpRequest();
// 请求成功回调函数
xhr.onload = e => {
    console.log('request success');
};
// 请求结束
xhr.onloadend = e => {
    console.log('request loadend');
};
// 请求出错
xhr.onerror = e => {
    console.log('request error');
};
// 请求超时
xhr.ontimeout = e => {
    console.log('request timeout');
};
// 请求回调函数.XMLHttpRequest标准又分为Level 1和Level 2,这是Level 1和的回调处理方式
// xhr.onreadystatechange = () => {
//    if (xhr.readyState !== 4) {
//      return;
//    }
//    const status = xhr.status;
//    if ((status >= 200 && status < 300) || status === 304) {
//      console.log('request success');
//    } else {
//      console.log('request error');
//    }
//  };

xhr.timeout = 0; // 设置超时时间,0表示永不超时
// 初始化请求
xhr.open('GET/POST/DELETE/...', '/url', true || false);
// 设置指望的返回数据类型 'json' 'text' 'document' ...
xhr.responseType = '';
// 设置请求头
xhr.setRequestHeader('', '');
// 发送请求
xhr.send(null || new FormData || 'a=1&b=2' || 'json字符串');

  这个是从网上找的。若是粗看官网提供的文档,可能须要好久的时间才能明白究竟怎么用。此处我先列出引用下。axios

JQuery ajax

  菜鸟教程:AJAX 是一种与服务器交换数据的技术,能够在不从新载入整个页面的状况下更新网页的一部分。后端

  基本语法:

$.ajax({
    type: 'POST',  // GET 或 POST
   url: url,    // 发送请求的 URL
   data: data,  // 要发送到服务器的数据
   dataType: dataType, // 预期的服务器响应的数据类型
   success: function () {}, // 请求成功时运行的函数
   error: function () {}   // 请求失败要运行的函数
});

  缺点:

  一、针对MVC的编程,不符合前端MVVM的浪潮

  二、基于原生XHR开发,而XHR自己的架构不清晰 (我以为此处应该是说官方给出的文档架构不清晰。)

  三、JQuery整个项目太大,单纯使用Ajax 却要引入整个JQuery,很是的不合理(采起个性化打包的方案又不能享受CDN服务)

  四、不符合关注分离(Separation of Concerns)的原则

  五、配置和调用方法很是的混乱,并且基于事件的异步模型不友好。(配置和调用方法很是的混乱:想作封装处理的时候,配置很差处理,须要作判断,若是方法不公用 就每次调用都得ajax一次,代码冗余。 )

  PS: MVVM (Model-View-ViewModel) 源自于经典的Model-View-Controller (MVC)模式。

    MVVM的出现促进了GUI前端开发与后端业务逻辑的分离,极大地提升了前端开发效率。

    MVVM 的核心是 ViewModel 层,它就像一个中转站(value converter),负责转换Model中的数据对象来让数据变得更容易管理和使用,该层向上与视图层进行双向数据绑定,向下与Model层经过接口请求进行数据交互,起呈上启下做用。View 层展示的不是 Model层的数据,而是ViewModel 的数据,由 ViewModel 负责与Model层交互,这就彻底解耦了View层和Model层,这个解耦是相当重要的,它是先后端分离方案实施的最重要一环。

  

 

axios

  axios 是一个基于 Promise 的 http请求库,能够用在浏览器和 node.js 中,本质上也是对原生XHR的封装,只不过它是Promise 的实现版本,符合最新的ES规则。

  基本语法:

const axios = require('axios')

// Make a request for a user with a given ID
axios.get('/url', {params})    // or axios.post ...
        .then(function(response){
                console.log(response)
        })
        .catch(function(error){
           console.log(error) 
        })

// Want to use async/await? Add the `async` keyword to your outer function/method
async function getUser(){
    try{
        const response = await axios.get('/user')
        console.log(response)                   
    }catch(error){
         console.error(error)  
    }  
}

  NOTE:  async/await 是ES6 中的内容,在 IE 及一些老版本的浏览器不支持,请谨慎使用。

  

  axios 的特征:

  一、从浏览器中建立XMLHttpRequest

  二、支持 Promise API

  三、客户端支持防止 CSRF

  四、提供了一些并发请求的接口(重要,方便了不少的操做)

  五、从 node.js 建立 http 请求

  六、拦截请求和响应

  七、转换请求和响应数据

  八、取消请求

  九、自动转换JSON数据

PS:防止CSRF(跨站请求伪造):就是让你的每一个请求都带一个从cookie中拿到的key,根据浏览器同源策略,假冒的网站是拿不到你 cookie 中的key的,这样,后台就能够轻松辨别出这个请求是不是用户在假冒网站上的误导输入,从而采起正确的策略。

 

fetch

// 一个简单的fetch 请求
fetch('http://example.com/movies.json')
    .then(function(response){
        return response.json()
    })
    .then(function(myJson){
       console.log(myJson) 
    })


// 一个带有参数的fetch请求
postData('http://example.com/answer',{answer: 42})
    .then(data => console.log(data))  // JSON from 'response.json()' call
    .catch(error => console.error(error))

function postData(url, data) {
  // Default options are marked with *
  return fetch(url, {
       body: JSON.stringify(data),  // must match 'Content-Type' header
       cache: 'no-cache',  // * default, no-cache, reload, force-cache, only-if-cached
        headers: {
            'user-agent': 'Mozilla/4.0 MDN Example',
             'content-type': 'application/json'
        },
        method: 'POST', // *GET, POST, PUT, DELETE, etc.
        mode: 'cors', // no-cors, cors, *same-origin
        redirect: 'follow', // manual, *follow, error
        referrer: 'no-referrer', // *client, no-referrer    
  })    
  .then(response => response.json()) // parses response to JSON      

  fetch 号称是 AJAX 的替代品,是在 ES6 出现的,使用了ES6 中的 promise 对象。Fetch 是基于 promise 设计的。 Fetch 的代码结构比起 ajax 简单多了, 参数有点像 JQuery ajax。 可是,必定要记住: fetch 不是 ajax的进一步封装,而是原生 JS , 没有使用 XMLHttpRequest 对象。

  fetch 的优势:

  一、符合关注分离,没有将输入、输出 和用事件来跟踪的状态混杂在一个对象中

  二、更好更方便的写法

 

  坦白说,上面的理由对我来讲彻底没有什么说服力,由于不论是Jquery仍是Axios都已经帮咱们把xhr封装的足够好,使用起来也足够方便,为何咱们还要花费大力气去学习fetch?

我认为fetch的主要优点就是:

  一、语法简洁,更加语义化

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

  三、同构方便,使用[isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch)

  四、更加底层,提供的 API 丰富 (request, response)

  五、脱离了 XHR,是 ES  规范中新的实现方式。

  

  最近在使用fetch的时候,也遇到了很多的问题:
fetch是一个低层次的API,你能够把它考虑成原生的XHR,因此使用起来并非那么舒服,须要进行封装。

  例如:

  一、fetch 只对网络请求报错,对400,500都看成成功的请求,服务器返回400, 500 错误码时并不会 reject,只有网络错误这些致使请求不能完成时, fetch 才会被 reject。须要封装去处理。

  二、fetch 默认不会带 cookie,须要添加配置项: fetch(url, {credentials: 'include'})

  三、fetch 不支持 abort (xhr 有个 xhr.abort 方法能够直接阻断请求),不支持超时控制,使用 setTimeout 及 Promise.reject 的实现的超时控制并不能阻止请求,请求过程继续在后台运行,形成了流量的浪费。

  四、fetch 没有办法原生监测请求的进度,而 XHR 能够。

  五、fetch 兼容性并不太好,IE 不支持

  PS:xhr send 完以后,本质请求已经发送了, 进入网络传输了,流量浪费已经发生了,abort只是在你将来某个时机调用,不想要这个请求了,那么即便远端服务器返回数据了,我浏览器拿到了,也不执行回调,由于已经abort了这个请求。(流量浪费已经发生了,只是abort 能够更好地控制要不要执行请求的回调。)

 

总结:axios既提供了并发的封装,也没有fetch的各类问题,并且体积也较小,当之无愧如今最应该选用的请求的方式。

 


并发 & 并行:

并发:在操做系统中,指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但 任一个时刻点上 只有一个程序 在处理机上运行。

并行:在操做系统中,一组程序 按独立异步 的速度执行,不管从微观仍是宏观,程序都是 一块儿执行的

 

 fetch 中的 AbortController:

  AbortController 接口表明一个控制器对象,容许你在须要时停止一个或多个DOM请求。

  这是一个实验中的功能。此功能某些浏览器尚在开发中。详情请见:https://developer.mozilla.org/zh-CN/docs/Web/API/FetchController

 

什么是回调地狱?

  因为某些业务的须要, 每一个接口都须要依赖前一个接口的返回,在代码中一次性写多层的回调嵌套,回调嵌套后的代码维护难度 和 没法快速排除bug ,这个就被称为 回调地狱。

  该如何解决回调地狱?在工做中的通常处理方式是使用 promise 或者async

  promise: 如 req1().then(req2).then(req3)

  Promise 的特性:(等待:pending;完成:resolve   拒绝:reject)

    一、promise 内部 分 微任何 和 宏任务 

    二、promise 自己是同步的,但它的成功的回调 .then 方法 是异步的。

    三、promise 的状态是不可逆的

    四、then return 出去的值,会被后面的 then 接收,若是后面还跟着 then 的话,catch同理

    五、promise 无论返回什么值,都会被包装成一个promise 对象,即便这个返回值是error

    六、then 接收到的值,若是不是一个函数,会穿透到后面的 then

    七、promise 对象若是 resolve 或者 reject 的也是一个 promise 对象,那么 promise 对象的状态会由 resolve 或者 reject 的 promise 对象的状态决定。


 

文章推荐:

Axios 源码深度剖析 - AJAX新王者: https://www.imooc.com/article/32292?block_id=tuijian_wz

并发和并行,异步与多线程区别:http://www.javashuo.com/article/p-xqexciwq-ca.html

相关文章
相关标签/搜索