Axios VS fetch

410 阅读2分钟
  • Axios和fetch都提供HTTP请求的方法,本文对二者进行对比
  1. 兼容性

    • Axios可以支持IE11,而fetch不支持IE,兼容性上稍差,但是可以通过引入polyfill解决该问题,而且fetch是浏览器内置的API,使用方便,在node端使用的话可以使用isomorphic-fetch库进行
        // 安装polyfill的库
        npm i whatwg-fetch --save
    
        import 'whatwg-fetch'
        window.fetch(...)
    
    
  2. 请求的细节上

    • Axios会自动将JSON对象进行stringify,而fetch里面需要手动做这一步,同样的对于返回值而言,Axios会直接返回JSON对象,而fetch里面则是需要额外进行response.json()的操作
        // Axios的请求方式
        const options = {
            url: 'someUrl.com',
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json;charset=UTF-8'
            },
            // 数据写在data字段中
            data: {
                name: 'Ryan',
                age: 24
            }
        };
    
        axios(options)
        .then(response => {
            console.log(response.status);
            return response.data;
        })
        .then(data => {
            console.log(data)
        });
    
        // fetch的请求方式
        const url = 'someUrl.com';
        const options = {
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json;charset=UTF-8'
            },
            // 数据写在body字段中,需要手动stringify
            body: JSON.stringify({
                a: 10,
                b: 20
            })
        };
    
        fetch(url, options)
        .then(response => {
            console.log(response.status);
            // 需要手动获得JSON对象
            return response.json()
        })
        .then(data => {
            console.log(data)
        });
    
    
  3. HTTP的拦截

    • Axios的一大feature就是提供了对请求的拦截以及响应的拦截,使得用户可以对请求参数或是返回结果进行统一的处理,fetch没有原生地提供该方法,但是可以通过全局改造fetch得到一个具有拦截作用的新fetch
        axios.interceptors.request.use(config => {
            // log a message before any HTTP request is sent
            console.log('Request was sent');
    
            return config;
        });
    
        // sent a GET request
        axios.get('someUrl.com/users')
        .then(response => {
            console.log(response.data);
        });
    
    
        // rewrite fetch
        fetch = (originalFetch => {
            return (...arguments) => {
                const result = originalFetch.apply(this, arguments);
                return result.then(console.log('Request was sent'));
            };
        })(fetch);
    
        fetch('someUrl.com/users')
        .then(response => response.json())
        .then(data => {
            console.log(data) 
        });
    
    
  4. 请求超时处理

    • Axios提供请求超时进行取消的选项,只需要在option中配置timeout字段即可,而fetch没有原生提供这项功能,但是可以通过AbortController对象来实现请求的abort
        axios({
            method: 'post',
            url: '/login',
            timeout: 4000,    // 4 seconds timeout
            data: {
                firstName: 'David',
                lastName: 'Pollock'
            }
        })
        .then(response => {/* handle the response */})
        .catch(error => console.error('timeout exceeded'))
    
    
        const controller = new AbortController();
        const options = {
            method: 'POST',
            signal: controller.signal,
            body: JSON.stringify({
                firstName: 'David',
                lastName: 'Pollock'
            })
        };  
        const promise = fetch('/login', options);
        // 利用AbortController对象的的abort方法像fetch请求发送signal,取消请求
        const timeoutId = setTimeout(() => controller.abort(), 4000);
    
        promise
        .then(response => {/* handle the response */})
        .catch(error => console.error('timeout exceeded'));
    
    
  5. 多请求处理

    • Axios提供axios.all()来同时进行多个请求,等所有请求结束之后返回结果,fetch可以利用Promise.all来实现一样的效果
    // 利用axios.all来处理多个请求,所有请求都完成之后resolve
    axios.all([
        axios.get('https://api.someUrl.com/a'), 
        axios.get('https://api.someUrl.com/b')
    ])
    .then(axios.spread((a, b) => {
        // 利用axios.spread来包裹回调,将返回的结果按顺序放进回调的参数内
        console.log(a.data);
        console.log(b.data);
    }))
    .catch(err => {
        console.log(err)
    });


    // fetch里面使用Promise.all来实现相同的效果
    Promise.all([
        fetch('https://api.someUrl.com/a'),
        fetch('https://api.someUrl.com/b')
    ])
    .then(async([res1, res2]) => {
        const a = await res1.json();
        const b = await res2.json();
        console.log(a);
        console.log(b);
    })
    .catch(error => {
        console.log(error);
    });