较为复杂的Fetch.js
import axios from 'axios';
import Qs from 'qs';
import { Toast } from 'vant';
import { cookie } from './common';
import {Message} from "element-ui";
import {refreshToken} from "../view/management/permission/refreshPermission";
import router from '../view/management/router';
const CODE_SUCCESS = 100000;
// 创建axios实例
const service = axios.create({
baseURL: process.env.BASE_API, // api的base_url
transformRequest: [function (data) {
return Qs.stringify(data);
}],
headers: {
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
timeout: 50000
});
// request拦截器
service.interceptors.request.use((config) => {
//domain(权限接口) 和 merchantCode(商户接口)
if(config.domain){
config.headers.domain = config.domain;
}
if(config.merchantCode === 'merchantChoose'){
config.headers.merchantCode = cookie.getCookie('merchantCode');
}
// if(config.merchantCode === 8001){
// config.headers.merchantCode = config.merchantCode;
// }
//只要不是登录的接口,都要设置权限
if(config.url.indexOf('auth/login')==-1){
config.headers.authorization = 'Bearer '+cookie.getCookie('interfaceToken')
}
// 当token涉及到临期,并且有interfaceToken 请求refresh_token
if( !cookie.getCookie('tokenValid') && cookie.getCookie('interfaceToken') && !cookie.getCookie('hasRresh')){
//刷新token的接口,加个cookie,控制只进入一次
cookie.setCookie('hasRresh',true);
refreshToken().then((data)=>{
config.headers.authorization = 'Bearer '+cookie.getCookie('interfaceToken')
//避免二次编译
if(config.headers["Content-Type"] === 'application/json'){
config.data = JSON.parse(config.data)
}
return axios.request(config);
})
}
return config;
}, (error) => {
// 可以在这里统一处理请求错误
Promise.reject(error);
});
service.interceptors.response.use((response) => {
let res = response.data;
if (res && res.code !== CODE_SUCCESS) {
//时间长不操作,token失效,跳转登录
if(res.code === 100141){
router.push('/login')
}
// 可以在这里统一处理响应错误
if(res.code !== 400201){
Message({
type: 'error',
message: response.data.msg == null?'请求异常':response.data.msg
});
console.log('liuli',res.msg)
throw 'bliliil'
// return Promise.reject(response.data);
}
}
return response.data;
}, (error) => {
// 可以在这里统一处理响应错误
return Promise.reject(error);
});
service.subPath = process.env.SUB_PATH;
export default service;
思考总结:
1、返回拦截器中处理逻辑
service.interceptors.response.use((response) => {
let res = response.data;
if (res && res.code !== 100000) {
return Promise.reject(response.data);
}
return response.data;
}, (error) => {
// 可以在这里统一处理响应错误
return Promise.reject(error);
});
当返回的code不等于100000时,但status为200,说明接口调通了,返回数据,但是可能是电话号码重复、密码出错等原因,需要给用户提示。
如果进入error,应该就是接口没调通
上述2种都返回了 Promise.reject对象。如果进入这里,调用接口地方必须用catch接收。否则报错

即便是.catch(()=>{})也需要
如果不想每次调用接口都加上.catch(),可以改写成抛出错误
throw response.data
throw error
会在控制台抛出错误。
如果此时调用接口的地方用了catch接收。throw就打印不出来了,错误被吞了,因此如果工程写了n多代码后,改Fetch配置一定要加小心
继续思考,为什么下面要抛出Promise.reject对象
if (res && res.code !== 100000) {
return Promise.reject(response.data);
}
如果直接返回数据,会进入调用接口方法的.then方法。Promise.reject的情况会进入.catch方法。是为了不同code进行区分处理逻辑 error中的return Promise.reject(error);同理
2、Content-Type为www-form格式,如果是json格式如何请求
在接口配置项目的地方增加
headers: {
'Content-Type': 'application/json'
},
transformRequest: [function (data) {
data = JSON.stringify(data)
return data
}],
3、为什么用qs转码

qs 会把参数用& 拼接
网友评论