HttpRequest.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import { _decorator, sys } from 'cc';
  2. /**
  3. * HTTP 请求工具类
  4. * 支持 GET/POST 方法,自动处理平台差异
  5. */
  6. export class HttpRequest {
  7. /**
  8. * 发送 GET 请求
  9. * @param url 请求地址
  10. * @param params 查询参数 (可选)
  11. * @param headers 请求头 (可选)
  12. */
  13. public static get(url: string, params?: Record<string, any>, headers?: Record<string, string>): Promise<any> {
  14. // 拼接查询参数
  15. const queryString = params ? this.serializeParams(params) : '';
  16. const fullUrl = queryString ? `${url}?${queryString}` : url;
  17. return this.request('GET', fullUrl, null, headers);
  18. }
  19. /**
  20. * 发送 POST 请求
  21. * @param url 请求地址
  22. * @param data 请求体数据 (可选)
  23. * @param headers 请求头 (可选)
  24. */
  25. public static post(url: string, data?: any, headers?: Record<string, string>): Promise<any> {
  26. // 设置默认 Content-Type
  27. const defaultHeaders = {
  28. 'Content-Type': 'application/json',
  29. ...headers
  30. };
  31. return this.request('POST', url, data, defaultHeaders);
  32. }
  33. /**
  34. * 核心请求方法
  35. * @param method HTTP 方法
  36. * @param url 请求地址
  37. * @param data 请求数据
  38. * @param headers 请求头
  39. */
  40. private static request(method: string, url: string, data?: any, headers?: Record<string, string>): Promise<any> {
  41. return new Promise((resolve, reject) => {
  42. // 微信小游戏平台使用 wx.request
  43. if (sys.platform === sys.Platform.WECHAT_GAME) {
  44. window['wx'].request({
  45. url,
  46. method: method as any,
  47. data,
  48. header: headers,
  49. success: (res) => {
  50. if (res.statusCode >= 200 && res.statusCode < 300) {
  51. resolve(res.data);
  52. } else {
  53. reject(new Error(`HTTP Error: ${res.statusCode}`));
  54. }
  55. },
  56. fail: (err) => {
  57. reject(new Error(`Request failed: ${err.errMsg}`));
  58. }
  59. });
  60. }
  61. // 其他平台使用 XMLHttpRequest
  62. else {
  63. const xhr = new XMLHttpRequest();
  64. xhr.open(method, url, true);
  65. // 设置请求头
  66. if (headers) {
  67. for (const key in headers) {
  68. if (headers.hasOwnProperty(key)) {
  69. xhr.setRequestHeader(key, headers[key]);
  70. }
  71. }
  72. }
  73. xhr.onreadystatechange = () => {
  74. if (xhr.readyState === 4) {
  75. if (xhr.status >= 200 && xhr.status < 300) {
  76. try {
  77. resolve(JSON.parse(xhr.responseText));
  78. } catch (e) {
  79. resolve(xhr.responseText);
  80. }
  81. } else {
  82. reject(new Error(`HTTP Error: ${xhr.status}`));
  83. }
  84. }
  85. };
  86. xhr.onerror = () => {
  87. reject(new Error('Network error'));
  88. };
  89. // 发送数据
  90. if (data) {
  91. if (headers && headers['Content-Type'] === 'application/json') {
  92. xhr.send(JSON.stringify(data));
  93. } else {
  94. xhr.send(data);
  95. }
  96. } else {
  97. xhr.send();
  98. }
  99. }
  100. });
  101. }
  102. /**
  103. * 序列化查询参数
  104. * @param params 参数对象
  105. * @returns 查询字符串
  106. */
  107. private static serializeParams(params: Record<string, any>): string {
  108. return Object.keys(params)
  109. .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
  110. .join('&');
  111. }
  112. }