zoukankan      html  css  js  c++  java
  • axios、fetch 和 ajax 等的区别详解

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

      axios、fetch 和 ajax的区别 在网络上存在很多文章。个人现针对自己的情况,来重新整理一份,便于自己记忆和理解。内容参考了网络上的众多文章。

    XMLHttpRequest

      浏览器通过XMLHttpRequest 对象进行 http 通信。

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

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

      常用语法:

      一个简单的 http 请求

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

        

      一个稍微完整的 http 请求

    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字符串');

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

    JQuery ajax

      菜鸟教程:AJAX 是一种与服务器交换数据的技术,可以在不重新载入整个页面的情况下更新网页的一部分。

      基本语法:

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

      缺点:

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

      2、基于原生XHR开发,而XHR本身的架构不清晰 (我觉得此处应该是说官方给出的文档架构不清晰。)

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

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

      5、配置和调用方法非常的混乱,而且基于事件的异步模型不友好。(配置和调用方法非常的混乱:想做封装处理的时候,配置不好处理,需要做判断,如果方法不公用 就每次调用都得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 的特征:

      1、从浏览器中创建XMLHttpRequest

      2、支持 Promise API

      3、客户端支持防止 CSRF

      4、提供了一些并发请求的接口(重要,方便了很多的操作)

      5、从 node.js 创建 http 请求

      6、拦截请求和响应

      7、转换请求和响应数据

      8、取消请求

      9、自动转换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 的优点:

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

      2、更好更方便的写法

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

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

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

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

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

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

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

      

      最近在使用fetch的时候,也遇到了不少的问题:
    fetch是一个低层次的API,你可以把它考虑成原生的XHR,所以使用起来并不是那么舒服,需要进行封装。

      例如:

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

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

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

      4、fetch 没有办法原生监测请求的进度,而 XHR 可以。

      5、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)

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

        2、promise 本身是同步的,但它的成功的回调 .then 方法 是异步的。

        3、promise 的状态是不可逆的

        4、then return 出去的值,会被后面的 then 接收,如果后面还跟着 then 的话,catch同理

        5、promise 不管返回什么值,都会被包装成一个promise 对象,即使这个返回值是error

        6、then 接收到的值,如果不是一个函数,会穿透到后面的 then

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


    文章推荐:

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

    并发和并行,异步与多线程区别:https://blog.csdn.net/woliuyunyicai/article/details/45165869

  • 相关阅读:
    函数式接口(Functional Interface)
    解决maven install报错:java.lang.NoClassDefFoundError: org/codehaus/plexus/compiler/util/scan/InclusionScanException
    logstash收集系统日志配置
    logstash的安装,启动与输出
    elasticsearch安装head插件
    elasticsearch启动常见错误
    elasticsearch的window的安装和启动
    linux下搭建jenkins
    jenkins在搭建中常见的问题
    window下操作jenkins查看页面的几种方式
  • 原文地址:https://www.cnblogs.com/bala/p/11650296.html
Copyright © 2011-2022 走看看