2023.11.15封装请求

master
dongmu 11 months ago
parent be12953e05
commit d859691873

@ -1,7 +1,17 @@
<script setup lang="ts">
import { useMemberStore } from '@/stores'
import { http } from '@/utils/http'
const memberStore = useMemberStore()
//
const getData = async () => {
const res = await http<string[]>({
url: '/home/banner',
method: 'GET',
})
console.log(res, 'res')
}
</script>
<template>
@ -10,7 +20,7 @@ const memberStore = useMemberStore()
<button
@tap="
memberStore.setProfile({
nickname: '黑马先锋',
nickname: '先锋',
})
"
size="mini"
@ -20,6 +30,7 @@ const memberStore = useMemberStore()
保存用户信息
</button>
<button @tap="memberStore.clearProfile()" size="mini" plain type="warn">清理用户信息</button>
<button @click="getData" size="mini" plain type="warn">请求测试</button>
</view>
</template>

@ -27,6 +27,17 @@ export const useMemberStore = defineStore(
},
// TODO: 持久化
{
persist: true,
// 网页端配置
// persist: true,
persist: {
storage: {
getItem(key) {
return uni.getStorageSync(key)
},
setItem(key, value) {
uni.setStorageSync(key, value)
},
},
},
},
)

@ -0,0 +1,90 @@
// src/utils/http.ts
import { useMemberStore } from '@/stores'
// 请求基地址
const baseURL = 'https://pcapi-xiaotuxian-front-devtest.itheima.net'
// 拦截器配置
const httpInterceptor = {
// 拦截前触发
invoke(options: UniApp.RequestOptions) {
// 1. 非 http 开头需拼接地址
if (!options.url.startsWith('http')) {
options.url = baseURL + options.url
}
// 2. 请求超时
options.timeout = 10000
// 3. 添加小程序端请求头标识
options.header = {
'source-client': 'miniapp',
...options.header,
}
// 4. 添加 token 请求头标识
const memberStore = useMemberStore()
const token = memberStore.profile?.token
if (token) {
options.header.Authorization = token
}
},
}
// 拦截 request 请求
uni.addInterceptor('request', httpInterceptor)
// 拦截 uploadFile 文件上传
uni.addInterceptor('uploadFile', httpInterceptor)
/**
*
* @param UniApp.RequestOptions
* @returns Promise
* 1. Promise
* 2.
* 2.1 res.data
* 2.2
* 3.
* 3.1 401 ->
* 3.2 ->
* 3.3 ->
*/
type Data<T> = {
code: string
msg: string
result: T
}
// 2.2 添加类型,支持泛型
export const http = <T>(options: UniApp.RequestOptions) => {
// 1. 返回 Promise 对象
return new Promise<Data<T>>((resolve, reject) => {
uni.request({
...options,
// 响应成功
success(res) {
// 状态码 2xx参考 axios 的设计
if (res.statusCode >= 200 && res.statusCode < 300) {
// 2.1 提取核心数据 res.data
resolve(res.data as Data<T>)
} else if (res.statusCode === 401) {
// 401错误 -> 清理用户信息,跳转到登录页
const memberStore = useMemberStore()
memberStore.clearProfile()
uni.navigateTo({ url: '/pages/login/login' })
reject(res)
} else {
// 其他错误 -> 根据后端错误信息轻提示
uni.showToast({
icon: 'none',
title: (res.data as Data<T>).msg || '请求错误',
})
reject(res)
}
},
// 响应失败
fail(err) {
uni.showToast({
icon: 'none',
title: '网络错误,换个网络试试',
})
reject(err)
},
})
})
}
Loading…
Cancel
Save