您现在的位置是:首页 >学无止境 >微前端nuxt3.0方便请求api可封装一个使用哈希算法出key值的http,http封装网站首页学无止境
微前端nuxt3.0方便请求api可封装一个使用哈希算法出key值的http,http封装
http.ts
import { hash } from 'ohash'
import type { FetchOptions } from 'ohmyfetch'
interface httpOptions {
source?: string
}
/**** 获取接口前缀 */
我这里为不同站点的接口做了区分,主站点为api,demo站点为demoapi
function GetPrefixUrl(source?: string) {
const {public : config} = useRuntimeConfig();
// 默认正式接口
let API_BASE = {
api: config.VITE_API,
demoapi: config.VITE_DEMO_API,
};
let prefixUrl = '';
switch (source) {
case 'demo':
prefixUrl = API_BASE.demoapi;
break;
default:
prefixUrl = API_BASE.api;
break;
}
//不是微前端的可以忽略这个例子
if (source === 'demoapi') {
const prefixcode = process.client ? 'demoapi' : 'api'; //判断接口是服务端还是客户端请求
return prefixUrl + prefixcode;
} else {
const prefixcode = process.client ? 'asyncapi' : 'api'; //判断接口是服务端还是客户端请求
return prefixUrl + prefixcode;
}
不是微前端的直接写:
const prefixcode = process.client ? 'asyncapi' : 'api';
return prefixUrl + prefixcode;
}
/** http 请求封装 */
export async function httpHandler<T, U extends httpOptions>(url: string, method: string, params: T | null, options: Partial<U> = {}) {
const config: FetchOptions = {};
const httpOptions = options;
let prefixUrl = GetPrefixUrl(httpOptions.source);
config.method = method;
config.headers = useRequestHeaders(['user-agent','x-forwarded-for','x-real-ip','accept-encoding','accept-language']);// 加了x-real-ip的作用是获取用户真实ip,根据自己需求是否要获取用户真实ip来保留日志记录
config.baseURL = prefixUrl;
const token = useCookie('token').value
if(token) {
config.headers.Authorization = `${token}`
}
if(config.headers['x-forwarded-for'] == undefined && config.headers['x-real-ip'] != undefined){config.headers['x-forwarded-for'] = config.headers['x-real-ip']};
if (params != null) {
if (method === 'get') {
config.params = params;
} else {
config.body = params;
}
}
let rst: any = {};
const key = hash(JSON.stringify(options) + url) // 使用hash算法获取不同的key值;当客户端传的参数不同时key值才会改变
const response = await useAsyncData(key, () =>
$fetch(url, config).catch((error) => {
// 当token失效跳转登录页登录
if(error.data.Code === 401) {
const redirect = route.path;
window.location.href = `/login?redirect=${redirect}`;
}
})
);
rst = <any>response.data.value;
switch (rst.Code) {
case 0:
if(rst.Data)
return rst.Data;
break;
case 401:
case 403:
// token 失效
console.error(rst.Message);
throw(rst.Message);
default:
console.error(rst.Message);
throw(rst.Message);
}
}
// type Partial<U> = {}
export async function httpGet<T, U>(url: string, options: Partial<U> = {}) {
const rst = await httpHandler<T, U>(url, 'get', null, options);
return rst;
}
export async function httpPost<T, U>(url: string, params?: T, options?: U) {
const rst = await httpHandler<T, U>(url, 'post', params, options);
return rst;
}
api/api.ts api文件夹下的api.ts
import { httpPost, httpGet } from '~/utils/http';
// p是参数
export const 组件使用名= (p: any) => httpPost('接口名', p);
// demo是不同站点的来源;不是微前端的可以忽略这个例子
export const 组件使用名= (p: any) => httpPost('接口名', p, demo);
demo.vue
import { 组件使用名,组件使用名1,组件使用名2 } from '~/api/api;
const data = await 组件使用名(); // 服务端请求
const [data1, data2] = await Promise.all([组件使用名1(),组件使用名2()]) // 多个接口请求
//客户端请求
const data = ()=> {
组件使用名().then(()=>{})
}