You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
153 lines
3.7 KiB
153 lines
3.7 KiB
import axios, { AxiosInstance, AxiosResponse, AxiosError, InternalAxiosRequestConfig } from 'axios'; |
|
import AsyncStorage from '@react-native-async-storage/async-storage'; |
|
import { API_BASE_URL, API_TIMEOUT, DEFAULT_HEADERS, STORAGE_KEYS } from '../../constants/config'; |
|
|
|
// 定义响应类型接口 |
|
export interface ApiResponse<T = any> { |
|
data: T; |
|
status: number; |
|
statusText: string; |
|
headers: any; |
|
} |
|
|
|
// 定义错误类型接口 |
|
export interface ApiError { |
|
message: string; |
|
status?: number; |
|
data?: any; |
|
} |
|
|
|
// 创建axios实例 |
|
const apiClient: AxiosInstance = axios.create({ |
|
baseURL: API_BASE_URL, |
|
timeout: API_TIMEOUT, |
|
headers: DEFAULT_HEADERS, |
|
}); |
|
|
|
// 请求拦截器 |
|
apiClient.interceptors.request.use( |
|
async (config: InternalAxiosRequestConfig) => { |
|
// 从AsyncStorage获取token |
|
const token = await AsyncStorage.getItem('token'); |
|
console.log(token); |
|
// 如果token存在,添加到请求头 |
|
if (token && config.headers) { |
|
config.headers.Authorization = `${token}`; |
|
} |
|
return config; |
|
}, |
|
(error: AxiosError) => { |
|
return Promise.reject(error); |
|
} |
|
); |
|
|
|
// 响应拦截器 |
|
apiClient.interceptors.response.use( |
|
(response: AxiosResponse) => { |
|
// 成功响应处理 |
|
return response; |
|
}, |
|
async (error: AxiosError<any>) => { |
|
// 错误响应处理 |
|
const { response } = error; |
|
|
|
// 处理401错误 (未授权) |
|
if (response && response.status === 401) { |
|
// 清除存储的token |
|
await AsyncStorage.removeItem(STORAGE_KEYS.AUTH_TOKEN); |
|
|
|
// 这里可以添加重定向到登录页面的逻辑 |
|
// 例如使用事件发射器或全局状态管理 |
|
} |
|
|
|
// 构建标准化的错误对象 |
|
const apiError: ApiError = { |
|
message: error.message || '网络请求失败', |
|
status: response?.status, |
|
data: response?.data |
|
}; |
|
|
|
return Promise.reject(apiError); |
|
} |
|
); |
|
|
|
// API方法封装 |
|
export const apiService = { |
|
// GET请求 |
|
async get<T>(url: string, params?: any, config?: any): Promise<T> { |
|
try { |
|
const response = await apiClient.get<T>(url, { params, ...config }); |
|
return response.data; |
|
} catch (error) { |
|
throw error; |
|
} |
|
}, |
|
|
|
// POST请求 |
|
async post<T>(url: string, data?: any, config?: any): Promise<T> { |
|
try { |
|
const response = await apiClient.post<T>(url, data, config); |
|
return response.data; |
|
} catch (error) { |
|
throw error; |
|
} |
|
}, |
|
|
|
// PUT请求 |
|
async put<T>(url: string, data?: any, config?: any): Promise<T> { |
|
try { |
|
const response = await apiClient.put<T>(url, data, config); |
|
return response.data; |
|
} catch (error) { |
|
throw error; |
|
} |
|
}, |
|
|
|
// PATCH请求 |
|
async patch<T>(url: string, data?: any, config?: any): Promise<T> { |
|
try { |
|
const response = await apiClient.patch<T>(url, data, config); |
|
return response.data; |
|
} catch (error) { |
|
throw error; |
|
} |
|
}, |
|
|
|
// DELETE请求 |
|
async delete<T>(url: string, config?: any): Promise<T> { |
|
try { |
|
const response = await apiClient.delete<T>(url, config); |
|
return response.data; |
|
} catch (error) { |
|
throw error; |
|
} |
|
}, |
|
|
|
// 上传文件 |
|
async upload<T>(url: string, formData: FormData, config?: any): Promise<T> { |
|
try { |
|
const uploadConfig = { |
|
headers: { |
|
'Content-Type': 'multipart/form-data', |
|
}, |
|
...config, |
|
}; |
|
|
|
const response = await apiClient.post<T>(url, formData, uploadConfig); |
|
return response.data; |
|
} catch (error) { |
|
throw error; |
|
} |
|
}, |
|
|
|
// 并发请求 |
|
async all<T>(requests: Promise<any>[]): Promise<T[]> { |
|
try { |
|
return await Promise.all(requests); |
|
} catch (error) { |
|
throw error; |
|
} |
|
} |
|
}; |
|
|
|
export default apiService;
|