music / src /services /api.js
ahutchen's picture
fix
40f23a9
// 基础API请求封装
class ApiClient {
constructor(baseURL = '', options = {}) {
this.baseURL = baseURL
this.timeout = options.timeout || 30000 // 改为30秒
this.headers = {
// 不要默认设置Content-Type,避免触发预检请求
...options.headers
}
}
// 基础请求方法
async request(url, options = {}) {
const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), this.timeout)
try {
const fullUrl = url.startsWith('http') ? url : `${this.baseURL}${url}`
// 对于所有请求,都不要添加默认的Content-Type头部,避免触发预检请求
const fetchOptions = {
signal: controller.signal,
...options
}
const response = await fetch(fullUrl, fetchOptions)
clearTimeout(timeoutId)
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
}
const contentType = response.headers.get('content-type')
if (contentType && contentType.includes('application/json')) {
return await response.json()
}
return await response.text()
} catch (error) {
clearTimeout(timeoutId)
if (error.name === 'AbortError') {
throw new Error('请求超时')
}
// 处理CORS错误,重新抛出错误让上层处理
if (error.toString().includes('CORS') || error.toString().includes('Failed to fetch')) {
console.error('CORS错误:', url, error)
throw new Error('网络请求失败,请检查网络连接')
}
throw error
}
}
// GET请求
get(url, params = {}) {
let fullUrl = url.startsWith('http') ? url : `${this.baseURL}${url}`
// 统一使用手动构建查询字符串的方式,避免URL对象可能带来的问题
const queryString = Object.entries(params)
.filter(([_, value]) => value !== undefined && value !== null)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`)
.join('&')
fullUrl = queryString ? `${fullUrl}?${queryString}` : fullUrl
return this.request(fullUrl, {
method: 'GET'
})
}
// POST请求
post(url, data = {}) {
return this.request(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...this.headers
},
body: JSON.stringify(data)
})
}
// PUT请求
put(url, data = {}) {
return this.request(url, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
...this.headers
},
body: JSON.stringify(data)
})
}
// DELETE请求
delete(url) {
return this.request(url, {
method: 'DELETE'
})
}
}
// 创建默认实例
export const apiClient = new ApiClient()
// 导出类以便创建自定义实例
export { ApiClient }