axios的二次封装、fetch的封装、及api接口管理规范

   日期:2020-09-21     浏览:248    评论:0    
核心提示:jQuery的ajax与axios和fetch优缺点1.jQuery ajax$.ajax({ type: 'POST', url: url, data: data, dataType: dataType, success: function () {}, error: function () {}});优缺点:本身是针对MVC的编程,不符合现在前端MVVM的浪潮基于原生的XHR开发,XHR本身的架构不清晰,已经有了fetch的替代方案JQue

jQuery的ajax与axios和fetch优缺点

1.jQuery ajax

$.ajax({ 
   type: 'POST',
   url: url,
   data: data,
   dataType: dataType,
   success: function () { },
   error: function () { }
});

优缺点:

  • 本身是针对MVC的编程,不符合现在前端MVVM的浪潮

  • 基于原生的XHR开发,XHR本身的架构不清晰,已经有了fetch的替代方案

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

2.axios

axios({ 
    method: 'post',
    url: '/user/12345',
    data: { 
        firstName: 'Fred',
        lastName: 'Flintstone'
    }
})
.then(function (response) { 
    console.log(response);
})
.catch(function (error) { 
    console.log(error);
});

优缺点:

  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 客户端支持防止CSRF(跨站请求伪造)
  • 提供了一些并发请求的接口(重要,方便了很多的操作)

3.fetch

try { 
  let response = await fetch(url);
  let data = response.json();
  console.log(data);
} catch(e) { 
  console.log("Oops, error", e);
}

优缺点:

  • 符合关注分离,没有将输入、输出和用事件来跟踪的状态混杂在一个对象里
  • 更好更方便的写法
  • 更加底层,提供的API丰富(request, response)
  • 脱离了XHR,是ES规范里新的实现方式
  • 1)fetcht只对网络请求报错,对400,500都当做成功的请求,需要封装去处理
  • 2)fetch默认不会带cookie,需要添加配置项
  • 3)fetch不支持abort,不支持超时控制,使用setTimeout及Promise.reject的实现的超时控制并不能阻止请求过程继续在后台运行,造成了量的浪费
  • 4)fetch没有办法原生监测请求的进度,而XHR可以

重点 axios的二次封装

import axios from 'axios'
import qs from 'qs'
switch (process.env.NODE_ENV) { 
    case "production":
        axios.defaults.baseURL = "http.....";
    case "test":
        axios.defaults.baseURL = "http.....";
    default:
        axios.defaults.baseURL = 'http'
}
axios.defaults.timeout = 10000;
axios.defaults.withCredentials = true;

axios.defaults.headers['Content-Type'] = 'application/x-www-form-urlencoded';
axios.defaults.transfromRequest = data => qs.stringify(data);
axios.interceptors.request.use(config => { 
        let token = localStorage.getItem('token');
        token && (config.headers.Authorization = token);
        return config;
    }, error => { 
        //如果拦截失败返回失败信息
        return Promise.reject(error)
    })
    
    // axios.defaults.validateStatus = status => { 
    // //自定义响应成功的http状态码,默认只有2或者3开头的响应码
    // return /^(2|3)\d{2}$/.test(status)
    // }
axios.interceptors.response.use(response => { 
    return response.data; //只返回响应的主体内容
}, error => { 
    if (error.response) { 
        //如果服务器有返回信息
        switch (error.response.status) { 
            case 401: //当前请求需要用户验证(一般是未登录)
                break;
            case 403: //服务器已经理解请求,但是拒绝执行他(一般是TOKEN过期)
                localStorage.removeItem('token');
                //跳转的登录页面
                break;
            case 404: //请求失败,请求所希望的到的资源未被在服务器上发现
                break;
        }
        return Promise.reject(error, response)
    } else {  // 如果服务器没有返回信息
        //断网处理
        if (!window.navigator.onLine) { 
            //网络断开了,可以让其跳转到断网页面
            return
        }
        return Promise.reject(error)
    }
})
export default axios

fetch的封装

import qs from 'qs'
import {  delete } from 'vue/types/umd';

let baseURL = '';
let baseURLArr = [{ 
    type: 'development',
    url: 'http://127.0.0.1:8080'
}, { 
    type: 'test',
    url: 'http://XXXX'
}, { 
    type: 'production',
    url: 'http://XXXX'
}];
baseURLArr.forEach(item => { 
    if (process.env.NODE_ENV === item.type) { 
        baseURL = item.url;
    }
})
export default function request(url, options = { }) { 
    url = baseURL + url;
    
    !options.method ? options.method = 'GET' : null;
    if (options.hasOwnProperty('params')) { 
        if (/^(GET|DELETe|HEAD|OPTIONS)$/i.test(options.method)) { 
            const ask = url.includes('?') ? '&' : '?';
            url += `${ ask}${ qs.stringify(params)}`;
        }
        delete options.params; //应为fetch中没有params,所以用完后赢移除
    }
    
    options = Object.assign({ 
        //允许跨域携带资源凭证 same-origin 同源可以 omit都拒绝
        credentials: 'include', //不管同源不同元都可以携带资源凭证
        //设置请求头
        headers: { }
    }, options);
    options.headers.Accept = 'application/json';
    
    const token = localStorage.getItem('token');
    token && (options.headers.Authorization = token);

    
    if (/^(POST|PUT)$/i.test(options.method)) { 
        !options.type ? options.type = 'urlencoded' : null;
        if (options.type === 'urlencoded') { 
            options.headers['Content-Type'] = 'application/x-www-form-urlencoded';
            options.body = qs.stringify(options.body);
        }
        if (options.type === 'json') { 
            options.headers['Content-Type'] = 'application/json';
            options.body = JSON.stringify(options.body);
        }
    }
    return fetch(url, options).then(response => { 
        if (!/^(2|3)\d$/.test(response.status)) { 
            switch (response.status) { 
                case 401: //当前请求需要用户验证(一般是未登录)
                    break;
                case 403: //服务器已经理解请求,但是拒绝执行他(一般是TOKEN过期)
                    localStorage.removeItem('token');
                    //跳转的登录页面
                    break;
                case 404: //请求失败,请求所希望的到的资源未被在服务器上发现
                    break;
            }
        }
        return response.json()
    }).catch(error => { 
        if (!window.navigator.onLine) { 
            //网络断开了,可以让其跳转到断网页面
            return;
        }
        return Promise.reject(error);
    })
}

api的集中式管理

将模块接口放在一个文件中集中管理

例如 user.js

import Axios from "../utile/Axios"
//导入封装好的axios

export const GetUserInfo = () => { 
        return new Promise((resolve, reject) => { 
            Axios.get('/member/ajax_login.php')
                .then(res => resolve(res))
                .catch(err => reject(err))
        })
    }
    
export const Exit = () => { 
        return new Promise((resolve, reject) => { 
            Axios.post("/member/index_login.php", {  dopost: 'exit' })
                .then(res => resolve(res))
                .catch(err => reject(err))
        })
    }
    
export const GetUserList = () => { 
        return new Promise((resolve, reject) => { 
            Axios.get('http://www.xingzhuang.com/user/list')
                .then(res => resolve(res))
                .catch(err => reject(err))
        })
    }
    
export const getUserGoodsList = () => { 
    return new Promise((resolve, reject) => { 
        Axios.post('/html/recommend/getRecommendGoodsList', {  siteId: 3, pageSize: 20, pageNum: 1 }
                //pageNum为参数
            ).then(res => resolve(res))
            .catch(err => reject(err))
    })
}

在api.js文件中进行集中导入


import {  GetUserInfo, Exit, GetUserList, getUserGoodsList } from './user'
import {  Category, GetMan, GetSelectind } from './cat'
export default { 
    GetUserInfo,
    Exit,
    GetUserList,
    getUserGoodsList,

    Category,
    GetMan,
    GetSelectind
}

可以在main.js中导入

import api from '../src/api/api'
Vue.prototype.$api = api

如果此时想在用户模块处使用Exit方法,只需要

 this.$api.Exit()

极大有利于接口管理的便捷性

 
打赏
 本文转载自:网络 
所有权利归属于原作者,如文章来源标示错误或侵犯了您的权利请联系微信13520258486
更多>最近资讯中心
更多>最新资讯中心
0相关评论

推荐图文
推荐资讯中心
点击排行
最新信息
新手指南
采购商服务
供应商服务
交易安全
关注我们
手机网站:
新浪微博:
微信关注:

13520258486

周一至周五 9:00-18:00
(其他时间联系在线客服)

24小时在线客服