Skip to content

网络请求问题

本页面收集了 uni-app 网络请求相关的常见问题和解决方案。

基础请求问题

Q: 请求无法发送或超时

问题描述:网络请求无法发送或经常超时。

解决方案

  1. 检查网络连接是否正常
  2. 检查请求 URL 是否正确,特别是协议部分(http/https)
  3. 增加请求超时时间:
    js
    uni.request({
      url: 'https://api.example.com/data',
      timeout: 10000, // 设置更长的超时时间(10秒)
      success: (res) => {
        console.log(res.data);
      },
      fail: (err) => {
        console.error('请求失败', err);
      }
    });
  4. 实现请求重试机制:
    js
    function requestWithRetry(options, maxRetries = 3) {
      let retryCount = 0;
      
      function sendRequest() {
        uni.request({
          ...options,
          fail: (err) => {
            if (retryCount < maxRetries) {
              retryCount++;
              console.log(`请求失败,第${retryCount}次重试`);
              setTimeout(sendRequest, 1000 * retryCount);
            } else if (options.fail) {
              options.fail(err);
            }
          }
        });
      }
      
      sendRequest();
    }

Q: 请求返回 404、500 等错误

问题描述:请求返回 HTTP 错误状态码。

解决方案

  1. 检查请求 URL 是否正确
  2. 检查服务器是否正常运行
  3. 检查请求参数是否符合接口要求
  4. 实现错误处理逻辑:
    js
    uni.request({
      url: 'https://api.example.com/data',
      success: (res) => {
        if (res.statusCode === 200) {
          // 请求成功
          console.log(res.data);
        } else {
          // 处理不同的错误状态码
          switch (res.statusCode) {
            case 404:
              console.error('资源不存在');
              break;
            case 401:
              console.error('未授权,请登录');
              // 跳转到登录页
              uni.navigateTo({ url: '/pages/login/login' });
              break;
            case 500:
              console.error('服务器内部错误');
              break;
            default:
              console.error(`请求错误: ${res.statusCode}`);
          }
        }
      },
      fail: (err) => {
        console.error('请求失败', err);
      }
    });

跨域问题

Q: H5 端请求跨域问题

问题描述:在 H5 端发起请求时遇到跨域限制。

解决方案

  1. 在服务端设置 CORS 头部:
    Access-Control-Allow-Origin: *
    Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
    Access-Control-Allow-Headers: Content-Type, Authorization
  2. 在 manifest.json 中配置代理:
    json
    {
      "h5": {
        "devServer": {
          "port": 8080,
          "disableHostCheck": true,
          "proxy": {
            "/api": {
              "target": "https://api.example.com",
              "changeOrigin": true,
              "pathRewrite": {
                "^/api": ""
              }
            }
          }
        }
      }
    }
  3. 使用 JSONP 方式请求(仅适用于 GET 请求)
  4. 使用服务端中转请求

Q: 小程序端请求域名限制

问题描述:小程序请求提示域名未授权。

解决方案

  1. 在小程序管理后台添加服务器域名到白名单
  2. 开发阶段可以在开发者工具中勾选"不校验合法域名"
  3. 使用小程序云函数中转请求
  4. 确保请求的 URL 使用 HTTPS 协议

数据格式问题

Q: 请求数据格式错误

问题描述:服务器无法正确解析请求数据。

解决方案

  1. 检查请求头 Content-Type 是否正确设置:
    js
    uni.request({
      url: 'https://api.example.com/data',
      method: 'POST',
      header: {
        'Content-Type': 'application/json'
      },
      data: JSON.stringify(postData),
      success: (res) => {
        console.log(res.data);
      }
    });
  2. 确保数据格式符合接口要求
  3. 检查是否需要对特殊字符进行编码
  4. 使用 uni.request 的 dataType 参数指定响应数据类型

Q: 响应数据解析错误

问题描述:无法正确解析服务器返回的数据。

解决方案

  1. 检查响应数据格式是否符合预期
  2. 使用 dataType 参数指定响应数据类型:
    js
    uni.request({
      url: 'https://api.example.com/data',
      dataType: 'json', // 指定响应数据为 JSON 格式
      success: (res) => {
        console.log(res.data);
      }
    });
  3. 手动解析响应数据:
    js
    uni.request({
      url: 'https://api.example.com/data',
      success: (res) => {
        try {
          const data = JSON.parse(res.data);
          console.log(data);
        } catch (e) {
          console.error('数据解析错误', e);
        }
      }
    });
  4. 检查服务器返回的数据编码是否正确

授权和认证问题

Q: 请求需要携带认证信息

问题描述:请求需要携带 token 或其他认证信息。

解决方案

  1. 在请求头中添加认证信息:
    js
    const token = uni.getStorageSync('token');
    
    uni.request({
      url: 'https://api.example.com/data',
      header: {
        'Authorization': `Bearer ${token}`
      },
      success: (res) => {
        console.log(res.data);
      }
    });
  2. 实现请求拦截器统一添加认证信息:
    js
    // request.js
    const request = (options) => {
      // 克隆原始选项
      const requestOptions = { ...options };
      
      // 添加基础 URL
      requestOptions.url = baseUrl + requestOptions.url;
      
      // 添加请求头
      requestOptions.header = {
        ...requestOptions.header,
        'Authorization': `Bearer ${uni.getStorageSync('token')}`
      };
      
      // 发送请求
      return new Promise((resolve, reject) => {
        uni.request({
          ...requestOptions,
          success: (res) => {
            if (res.statusCode === 200) {
              resolve(res.data);
            } else if (res.statusCode === 401) {
              // 处理认证失败
              uni.navigateTo({ url: '/pages/login/login' });
              reject(new Error('认证失败'));
            } else {
              reject(new Error(`请求失败: ${res.statusCode}`));
            }
          },
          fail: (err) => {
            reject(err);
          }
        });
      });
    };
  3. 使用 cookie 存储会话信息(需要服务端支持)
  4. 实现 token 刷新机制处理过期问题

Q: 登录状态失效问题

问题描述:用户登录状态失效,需要重新登录。

解决方案

  1. 实现 token 过期检测和自动刷新:
    js
    // 检查 token 是否过期
    function isTokenExpired(token) {
      if (!token) return true;
      
      try {
        // 假设 token 是 JWT 格式
        const payload = JSON.parse(atob(token.split('.')[1]));
        return payload.exp < Date.now() / 1000;
      } catch (e) {
        return true;
      }
    }
    
    // 刷新 token
    async function refreshToken() {
      try {
        const refreshToken = uni.getStorageSync('refreshToken');
        const res = await uni.request({
          url: 'https://api.example.com/refresh',
          method: 'POST',
          data: { refreshToken }
        });
        
        if (res.statusCode === 200) {
          uni.setStorageSync('token', res.data.token);
          uni.setStorageSync('refreshToken', res.data.refreshToken);
          return res.data.token;
        } else {
          throw new Error('刷新 token 失败');
        }
      } catch (e) {
        // 刷新失败,需要重新登录
        uni.removeStorageSync('token');
        uni.removeStorageSync('refreshToken');
        uni.navigateTo({ url: '/pages/login/login' });
        throw e;
      }
    }
  2. 统一处理 401 错误,自动跳转到登录页
  3. 实现会话保持机制,定期刷新 token
  4. 使用本地存储保存用户信息,减少重复登录

请求管理和优化

Q: 如何取消正在进行的请求

问题描述:需要取消已发出但尚未完成的请求。

解决方案

  1. 使用 requestTask 对象取消请求:
    js
    const requestTask = uni.request({
      url: 'https://api.example.com/data',
      success: (res) => {
        console.log(res.data);
      }
    });
    
    // 取消请求
    requestTask.abort();
  2. 实现请求管理器,跟踪和取消请求:
    js
    class RequestManager {
      constructor() {
        this.requests = new Map();
      }
      
      // 添加请求
      addRequest(key, requestTask) {
        this.requests.set(key, requestTask);
      }
      
      // 移除请求
      removeRequest(key) {
        this.requests.delete(key);
      }
      
      // 取消请求
      cancelRequest(key) {
        const requestTask = this.requests.get(key);
        if (requestTask) {
          requestTask.abort();
          this.removeRequest(key);
        }
      }
      
      // 取消所有请求
      cancelAllRequests() {
        this.requests.forEach(requestTask => {
          requestTask.abort();
        });
        this.requests.clear();
      }
    }
    
    // 使用请求管理器
    const requestManager = new RequestManager();
    
    function sendRequest(url, key) {
      const requestTask = uni.request({
        url,
        complete: () => {
          requestManager.removeRequest(key);
        }
      });
      
      requestManager.addRequest(key, requestTask);
      return requestTask;
    }
    
    // 页面卸载时取消所有请求
    onUnload() {
      requestManager.cancelAllRequests();
    }
  3. 在页面切换或组件卸载时主动取消请求
  4. 使用超时机制自动取消长时间未响应的请求

Q: 如何处理并发请求限制

问题描述:同时发起大量请求导致性能问题或被服务器限流。

解决方案

  1. 实现请求队列,控制并发数量:
    js
    class RequestQueue {
      constructor(maxConcurrent = 5) {
        this.queue = [];
        this.running = 0;
        this.maxConcurrent = maxConcurrent;
      }
      
      add(requestFn) {
        return new Promise((resolve, reject) => {
          this.queue.push({ requestFn, resolve, reject });
          this.run();
        });
      }
      
      run() {
        if (this.running >= this.maxConcurrent || this.queue.length === 0) {
          return;
        }
        
        const { requestFn, resolve, reject } = this.queue.shift();
        this.running++;
        
        requestFn()
          .then(resolve)
          .catch(reject)
          .finally(() => {
            this.running--;
            this.run();
          });
      }
    }
    
    // 使用请求队列
    const requestQueue = new RequestQueue(3);
    
    function sendRequest(url) {
      return requestQueue.add(() => {
        return new Promise((resolve, reject) => {
          uni.request({
            url,
            success: resolve,
            fail: reject
          });
        });
      });
    }
  2. 合并请求,减少请求次数
  3. 使用批量接口一次获取多条数据
  4. 实现请求节流,避免短时间内重复请求同一资源

网络状态管理

Q: 如何处理弱网或离线情况

问题描述:在网络不稳定或离线情况下,请求失败影响用户体验。

解决方案

  1. 监听网络状态变化:
    js
    // 监听网络状态
    uni.onNetworkStatusChange(function(res) {
      console.log(`网络类型: ${res.networkType}`);
      console.log(`是否已连接: ${res.isConnected}`);
      
      if (res.isConnected) {
        // 网络恢复,可以重新发送失败的请求
        resendFailedRequests();
      } else {
        // 网络断开,提示用户
        uni.showToast({
          title: '网络连接已断开',
          icon: 'none'
        });
      }
    });
    
    // 获取当前网络状态
    uni.getNetworkType({
      success: (res) => {
        console.log(`当前网络类型: ${res.networkType}`);
      }
    });
  2. 实现离线数据缓存和同步:
    js
    // 带离线缓存的请求函数
    async function requestWithCache(url, options = {}) {
      const cacheKey = `cache_${url}`;
      
      try {
        // 检查网络状态
        const networkStatus = await getNetworkStatus();
        
        if (networkStatus.isConnected) {
          // 有网络,发送请求
          const response = await sendRequest(url, options);
          
          // 缓存响应数据
          uni.setStorageSync(cacheKey, {
            data: response.data,
            timestamp: Date.now()
          });
          
          return response.data;
        } else {
          // 无网络,使用缓存
          const cache = uni.getStorageSync(cacheKey);
          
          if (cache) {
            console.log(`使用缓存数据: ${url}`);
            return cache.data;
          } else {
            throw new Error('无网络连接且无缓存数据');
          }
        }
      } catch (error) {
        // 请求失败,尝试使用缓存
        const cache = uni.getStorageSync(cacheKey);
        
        if (cache) {
          console.log(`请求失败,使用缓存数据: ${url}`);
          return cache.data;
        } else {
          throw error;
        }
      }
    }
  3. 提供离线模式,允许用户在无网络时浏览缓存内容
  4. 实现请求队列,在网络恢复时自动重发失败的请求

Q: 如何优化弱网环境下的用户体验

问题描述:在网络不稳定的环境下,请求缓慢影响用户体验。

解决方案

  1. 实现渐进式加载,先显示骨架屏或占位内容
  2. 优先加载关键数据,延迟加载非关键内容
  3. 减小请求数据量,使用分页或按需加载
  4. 提供加载状态反馈:
    js
    // 带加载状态的请求函数
    async function requestWithLoading(url, options = {}) {
      const showLoading = options.showLoading !== false;
      
      if (showLoading) {
        uni.showLoading({
          title: options.loadingText || '加载中...',
          mask: options.loadingMask || false
        });
      }
      
      try {
        const response = await sendRequest(url, options);
        return response;
      } finally {
        if (showLoading) {
          uni.hideLoading();
        }
      }
    }

文件上传和下载

Q: 文件上传失败或中断

问题描述:上传文件时失败或中断。

解决方案

  1. 使用分片上传大文件:
    js
    // 分片上传文件
    async function uploadFileInChunks(filePath, options = {}) {
      const chunkSize = options.chunkSize || 1024 * 1024; // 默认 1MB 一片
      const fileInfo = await getFileInfo(filePath);
      const totalSize = fileInfo.size;
      const chunks = Math.ceil(totalSize / chunkSize);
      
      // 创建上传任务
      const uploadId = await createUploadTask(fileInfo.name, totalSize);
      
      // 上传分片
      for (let i = 0; i < chunks; i++) {
        const start = i * chunkSize;
        const end = Math.min(start + chunkSize, totalSize);
        
        await uploadChunk({
          filePath,
          uploadId,
          chunkIndex: i,
          start,
          end
        });
        
        // 更新进度
        if (options.onProgress) {
          options.onProgress({
            progress: Math.floor((i + 1) / chunks * 100),
            totalChunks: chunks,
            currentChunk: i + 1
          });
        }
      }
      
      // 完成上传
      return await completeUpload(uploadId);
    }
  2. 实现断点续传:
    js
    // 断点续传
    async function resumableUpload(filePath, options = {}) {
      const fileInfo = await getFileInfo(filePath);
      const uploadKey = `upload_${fileInfo.name}_${fileInfo.size}`;
      
      // 尝试获取上传进度
      let uploadProgress = uni.getStorageSync(uploadKey) || {
        uploadId: null,
        uploadedChunks: []
      };
      
      // 如果没有上传ID或上传已过期,创建新的上传任务
      if (!uploadProgress.uploadId) {
        uploadProgress.uploadId = await createUploadTask(fileInfo.name, fileInfo.size);
        uploadProgress.uploadedChunks = [];
      }
      
      // 计算剩余需要上传的分片
      const chunkSize = options.chunkSize || 1024 * 1024;
      const totalChunks = Math.ceil(fileInfo.size / chunkSize);
      const remainingChunks = [];
      
      for (let i = 0; i < totalChunks; i++) {
        if (!uploadProgress.uploadedChunks.includes(i)) {
          remainingChunks.push(i);
        }
      }
      
      // 上传剩余分片
      for (const chunkIndex of remainingChunks) {
        const start = chunkIndex * chunkSize;
        const end = Math.min(start + chunkSize, fileInfo.size);
        
        await uploadChunk({
          filePath,
          uploadId: uploadProgress.uploadId,
          chunkIndex,
          start,
          end
        });
        
        // 更新已上传分片记录
        uploadProgress.uploadedChunks.push(chunkIndex);
        uni.setStorageSync(uploadKey, uploadProgress);
        
        // 更新进度
        if (options.onProgress) {
          options.onProgress({
            progress: Math.floor(uploadProgress.uploadedChunks.length / totalChunks * 100),
            totalChunks,
            uploadedChunks: uploadProgress.uploadedChunks.length
          });
        }
      }
      
      // 完成上传
      const result = await completeUpload(uploadProgress.uploadId);
      
      // 清理上传记录
      uni.removeStorageSync(uploadKey);
      
      return result;
    }
  3. 添加重试机制,自动重试失败的上传
  4. 优化上传参数,如超时时间和并发数

Q: 文件下载问题

问题描述:文件下载失败或无法打开下载的文件。

解决方案

  1. 使用 uni.downloadFile API 下载文件:
    js
    // 下载文件并显示进度
    function downloadFile(url, options = {}) {
      const downloadTask = uni.downloadFile({
        url,
        header: options.header,
        timeout: options.timeout || 60000,
        success: (res) => {
          if (res.statusCode === 200) {
            console.log('下载成功', res.tempFilePath);
            
            if (options.saveFile) {
              // 保存文件到本地
              uni.saveFile({
                tempFilePath: res.tempFilePath,
                success: (saveRes) => {
                  console.log('文件已保存', saveRes.savedFilePath);
                  if (options.success) options.success(saveRes.savedFilePath);
                },
                fail: (err) => {
                  console.error('保存文件失败', err);
                  if (options.fail) options.fail(err);
                }
              });
            } else if (options.success) {
              options.success(res.tempFilePath);
            }
          } else {
            console.error('下载失败', res);
            if (options.fail) options.fail(new Error(`下载失败: ${res.statusCode}`));
          }
        },
        fail: (err) => {
          console.error('下载失败', err);
          if (options.fail) options.fail(err);
        }
      });
      
      // 监听下载进度
      if (options.onProgress) {
        downloadTask.onProgressUpdate((res) => {
          options.onProgress({
            progress: res.progress,
            totalBytesWritten: res.totalBytesWritten,
            totalBytesExpectedToWrite: res.totalBytesExpectedToWrite
          });
        });
      }
      
      return downloadTask;
    }
  2. 检查文件保存路径和权限
  3. 实现大文件分片下载
  4. 添加文件完整性校验,如 MD5 校验

最佳实践

请求封装和统一处理

  1. 封装请求函数,统一处理错误和响应:

    js
    // request.js
    
    // 基础配置
    const config = {
      baseUrl: 'https://api.example.com',
      timeout: 10000,
      header: {
        'Content-Type': 'application/json'
      }
    };
    
    // 请求拦截器
    const requestInterceptors = [];
    
    // 响应拦截器
    const responseInterceptors = [];
    
    // 添加请求拦截器
    function addRequestInterceptor(interceptor) {
      requestInterceptors.push(interceptor);
    }
    
    // 添加响应拦截器
    function addResponseInterceptor(interceptor) {
      responseInterceptors.push(interceptor);
    }
    
    // 处理请求配置
    function processRequestConfig(options) {
      let processedOptions = { ...config, ...options };
      
      // 应用请求拦截器
      for (const interceptor of requestInterceptors) {
        processedOptions = interceptor(processedOptions);
      }
      
      return processedOptions;
    }
    
    // 处理响应数据
    function processResponse(response, options) {
      let processedResponse = response;
      
      // 应用响应拦截器
      for (const interceptor of responseInterceptors) {
        processedResponse = interceptor(processedResponse, options);
      }
      
      return processedResponse;
    }
    
    // 请求函数
    function request(options) {
      const processedOptions = processRequestConfig(options);
      
      return new Promise((resolve, reject) => {
        uni.request({
          ...processedOptions,
          success: (res) => {
            const processedResponse = processResponse(res, processedOptions);
            
            if (processedResponse.statusCode >= 200 && processedResponse.statusCode < 300) {
              resolve(processedResponse.data);
            } else {
              reject(processedResponse);
            }
          },
          fail: (err) => {
            reject(err);
          }
        });
      });
    }
    
    // 导出请求方法
    export default {
      request,
      get: (url, data, options = {}) => request({ url, data, method: 'GET', ...options }),
      post: (url, data, options = {}) => request({ url, data, method: 'POST', ...options }),
      put: (url, data, options = {}) => request({ url, data, method: 'PUT', ...options }),
      delete: (url, data, options = {}) => request({ url, data, method: 'DELETE', ...options }),
      addRequestInterceptor,
      addResponseInterceptor
    };
  2. 添加全局错误处理:

    js
    // 添加全局错误处理拦截器
    addResponseInterceptor((response) => {
      if (response.statusCode === 401) {
        // 处理未授权错误
        uni.showToast({
          title: '登录已过期,请重新登录',
          icon: 'none'
        });
        
        // 跳转到登录页
        setTimeout(() => {
          uni.navigateTo({ url: '/pages/login/login' });
        }, 1500);
      } else if (response.statusCode >= 500) {
        // 处理服务器错误
        uni.showToast({
          title: '服务器错误,请稍后再试',
          icon: 'none'
        });
      }
      
      return response;
    });

数据缓存策略

  1. 实现数据缓存和过期控制:

    js
    // cache.js
    
    // 缓存数据到本地存储
    function setCache(key, data, expireTime = 3600) {
      uni.setStorageSync(key, {
        data,
        expireAt: Date.now() + expireTime * 1000
      });
    }
    
    // 获取缓存数据
    function getCache(key) {
      const cache = uni.getStorageSync(key);
      
      if (!cache) return null;
      
      // 检查是否过期
      if (cache.expireAt && cache.expireAt < Date.now()) {
        uni.removeStorageSync(key);
        return null;
      }
      
      return cache.data;
    }
    
    // 带缓存的请求函数
    async function requestWithCache(url, options = {}) {
      const cacheKey = `cache_${url}_${JSON.stringify(options.data || {})}`;
      const useCache = options.useCache !== false;
      const cacheTime = options.cacheTime || 300; // 默认缓存5分钟
      
      // 如果启用缓存,尝试从缓存获取
      if (useCache) {
        const cachedData = getCache(cacheKey);
        if (cachedData) {
          return cachedData;
        }
      }
      
      // 发送请求
      const response = await request({ url, ...options });
      
      // 缓存响应数据
      if (useCache) {
        setCache(cacheKey, response, cacheTime);
      }
      
      return response;
    }
  2. 实现数据预加载:

    js
    // 预加载常用数据
    function preloadCommonData() {
      // 预加载用户信息
      requestWithCache('/api/user/info', { cacheTime: 3600 });
      
      // 预加载应用配置
      requestWithCache('/api/config', { cacheTime: 86400 });
      
      // 预加载其他常用数据
      // ...
    }
    
    // 在应用启动时调用
    // App.vue
    onLaunch() {
      preloadCommonData();
    }

如果您遇到的问题在本页面没有找到解决方案,请查看 uni-app 官方文档 或在 uni-app 社区 中寻求帮助。

常见错误代码解析

网络请求错误码

错误码说明可能原因解决方案
-1未知错误网络异常、请求超时等检查网络连接,增加超时时间
401未授权用户未登录或 token 已过期重新登录获取新 token
403禁止访问用户无权限访问该资源检查用户权限设置
404资源不存在URL 错误或资源已删除检查请求 URL 是否正确
500服务器内部错误服务端代码异常联系后端开发人员修复
502网关错误服务器重启或负载均衡问题稍后重试或联系服务提供商
503服务不可用服务器维护或过载稍后重试

小程序请求特有错误

错误码说明可能原因解决方案
12000网络出错网络连接失败检查网络连接
12001请求超时服务器响应时间过长增加超时时间或优化服务器响应速度
12002请求被拦截域名未配置或 HTTPS 证书无效检查域名配置和 HTTPS 证书
12003请求资源不存在URL 错误检查请求 URL
12006请求被中断调用了 abort 方法或网络断开检查是否有代码主动中断请求

调试技巧

网络请求调试

  1. 使用控制台查看请求

    • 在 HBuilderX 中使用 console.log 打印请求参数和响应结果
    • 在微信开发者工具中使用 Network 面板查看请求详情
  2. 添加调试日志

    js
    // 添加请求日志拦截器
    addRequestInterceptor((options) => {
      console.log('请求参数:', options);
      return options;
    });
    
    // 添加响应日志拦截器
    addResponseInterceptor((response, options) => {
      console.log(`请求 ${options.url} 响应:`, response);
      return response;
    });
  3. 使用抓包工具

    • 使用 Charles、Fiddler 等工具抓包分析请求和响应
    • 在 App 端可以使用代理方式进行抓包

常见问题排查流程

  1. 请求无法发送

    • 检查网络连接
    • 检查请求 URL 是否正确
    • 检查小程序域名是否已配置
    • 检查 HTTPS 证书是否有效
  2. 请求发送但无响应

    • 检查请求是否超时
    • 检查服务器是否正常运行
    • 检查防火墙或安全策略是否拦截
  3. 请求返回错误

    • 检查请求参数是否正确
    • 检查认证信息是否有效
    • 查看服务器日志了解具体错误
  4. 数据解析错误

    • 检查响应数据格式
    • 检查 dataType 参数是否正确
    • 检查是否有特殊字符导致解析失败

性能优化建议

  1. 减少请求次数

    • 合并多个请求
    • 使用批量接口
    • 实现数据缓存策略
  2. 减小请求数据量

    • 只请求必要的数据
    • 使用分页加载
    • 压缩请求和响应数据
  3. 优化请求时机

    • 避免重复请求
    • 实现请求节流和防抖
    • 预加载可能需要的数据
  4. 优化错误处理

    • 实现优雅的降级策略
    • 提供友好的错误提示
    • 自动重试非关键请求

参考资源

一次开发,多端部署 - 让跨平台开发更简单