diff --git a/web/request.js b/web/request.js index 70926d9..7ac2c6d 100644 --- a/web/request.js +++ b/web/request.js @@ -1,104 +1,155 @@ -import { getStorage, removeStorage } from '../export.js' +import { buildNumber, getStorage, removeStorage, version } from '../export' import starCloudInstance from '../star-cloud' import { Result } from '../constant' -/* - * config - * baseUrl: 请求域名 - * url: 请求路径 - * method: 请求方法 - * header: 请求头 - * token: 请求token - * data: 请求参数 - * */ - -const request = config => { - let timer - let res = null // 在外部定义res,避免finally块报错 +const request = (config) => { return new Promise(async resolve => { - const baseConfig = starCloudInstance.getConfig() - - const token = config?.token ? config.token : getStorage('starCloudToken') - // 请求地址 - const URL = config.baseUrl ? config.baseUrl + config.url : baseConfig.baseUrl + config.url - - // 默认请求头 - const headerDefault = { - version: baseConfig.version + '+' + baseConfig.buildNumber - } - const header = { - ...headerDefault, - ...config.header - } - const method = config.method || 'POST' - const data = { - ...config.data, - accessToken: token, - clientId: starCloudInstance.clientId - } - const timestamp = new Date().getTime() - - // 超时处理 - timer = setTimeout(() => { - resolve(new Result(Result.Fail.code, {}, '网络访问失败,请检查网络是否正常')) - }, 3200) - try { - const response = await fetch(URL, { - method, - headers: { - ...header, - 'Content-Type': 'application/json' - }, - body: JSON.stringify(data) - }) + const starCloud = starCloudInstance + const baseConfig = starCloud.getConfig() + const token = config?.token || getStorage('starCloudToken') + const timestamp = new Date().getTime() - res = await response.json() // 在这里将res赋值 - if (timer) { - clearTimeout(timer) + // 获取正确的版本号和构建号 + let currentVersion = typeof version === 'function' ? version() : version + let currentBuildNumber = typeof buildNumber === 'function' ? buildNumber() : buildNumber + + // 构建请求 URL + const baseUrl = config.baseUrl || baseConfig.baseUrl + let url = baseUrl + config.url + + // 构建请求数据 + const requestData = { + ...config.data, + accessToken: token, + clientId: starCloud.clientId } - if (response.ok) { - const { errcode, errmsg, data } = res - if (errcode === 10003) { - removeStorage('starCloudToken') - removeStorage('starCloudUser') - const { code } = await starCloudInstance.login({ - username: starCloudInstance.starCloudAccountInfo.username, - password: starCloudInstance.starCloudAccountInfo.password, - uid: starCloudInstance.starCloudAccountInfo.uid - }) - if (code === Result.Success.code) { - resolve(await request(config)) + // 处理 GET 请求的参数 + const method = (config.method || 'POST').toUpperCase() + if (method === 'GET') { + const params = new URLSearchParams() + Object.entries(requestData).forEach(([key, value]) => { + if (value != null) { + params.append(key, String(value)) + } + }) + const queryString = params.toString() + if (queryString) { + url += (url.includes('?') ? '&' : '?') + queryString + } + } + + // 创建 XHR 对象 + const xhr = new XMLHttpRequest() + let timer = null + + // 设置超时 + xhr.timeout = 3200 + + // 打开连接 + xhr.open(method, url, true) + + // 设置请求头 + xhr.setRequestHeader('Content-Type', 'application/json') + xhr.setRequestHeader('version', `${currentVersion}+${currentBuildNumber}`) + if (config.header) { + Object.entries(config.header).forEach(([key, value]) => { + if (value != null) { + xhr.setRequestHeader(key, String(value)) + } + }) + } + + // 关闭 withCredentials,使用其他方式传递凭证 + xhr.withCredentials = false + + // 处理响应 + xhr.onload = async function() { + if (timer) { + clearTimeout(timer) + } + + if (xhr.status === 200) { + try { + const responseData = JSON.parse(xhr.responseText) + const code = responseData.errcode + const message = responseData.errmsg + + // 处理 token 过期 + if (code === 10003) { + removeStorage('starCloudToken') + removeStorage('starCloudUser') + const loginResult = await starCloud.login({ + username: starCloud.starCloudAccountInfo.username, + password: starCloud.starCloudAccountInfo.password, + uid: starCloud.starCloudAccountInfo.uid + }) + if (loginResult.code === Result.Success.code) { + return resolve(await request(config)) + } + } + + // 记录日志 + console.log('请求完成', { + env: baseConfig.name, + url: url.replace(baseUrl, ''), + req: config?.data || {}, + code: responseData.errcode, + res: responseData.data, + token: config.header?.authorization || '', + message: responseData.errmsg, + duration: new Date().getTime() - timestamp + }) + + resolve({ + code, + data: responseData.data, + message + }) + } catch (error) { + console.log('解析响应失败', error) + resolve(new Result(Result.Fail.code, {}, '网络访问失败,请检查网络是否正常')) } } else { - resolve({ - code: errcode, - data, - message: errmsg - }) + resolve(new Result(Result.Fail.code, {}, '网络访问失败,请检查网络是否正常')) } - } else { + } + + // 处理错误 + xhr.onerror = function() { + if (timer) { + clearTimeout(timer) + } + console.log('网络访问失败', xhr.status, xhr.statusText) resolve(new Result(Result.Fail.code, {}, '网络访问失败,请检查网络是否正常')) } - } catch (error) { - console.log('网络访问失败', error) - if (timer) { - clearTimeout(timer) + + // 处理超时 + xhr.ontimeout = function() { + if (timer) { + clearTimeout(timer) + } + console.log('请求超时') + resolve(new Result(Result.Fail.code, {}, '网络访问失败,请检查网络是否正常')) } + + // 发送请求 + if (method === 'GET') { + xhr.send() + } else { + xhr.send(JSON.stringify(requestData)) + } + + // 额外的超时保护 + timer = setTimeout(() => { + xhr.abort() + resolve(new Result(Result.Fail.code, {}, '网络访问失败,请检查网络是否正常')) + }, 3200) + + } catch (error) { + console.log('请求错误', error) resolve(new Result(Result.Fail.code, {}, '网络访问失败,请检查网络是否正常')) - } finally { - // 访问res时确保它已定义 - console.log(URL.substring(baseConfig.baseUrl.length + 1), { - env: baseConfig.name, - url: URL.substring(baseConfig.baseUrl.length + 1), - req: config?.data || {}, - code: res?.errcode || null, // 如果res未定义,fallback为null - res: res?.data || null, // 如果res未定义,fallback为null - token: header?.authorization || '', - message: res?.errmsg || '', // 如果res未定义,fallback为空字符串 - duration: new Date().getTime() - timestamp - }) } }) }