uniapp --发送请求请求数据

'# uniapp --发送请求请求数据

一、背景与问题

在uni-app开发中,网络请求是连接前后端的核心桥梁。开发者需要通过uni.request等API与服务器进行数据交互,但实际开发中常遇到以下挑战:

  1. 跨域问题:微信小程序等平台对跨域请求有严格限制
  2. 请求参数复杂性:需要处理Token、签名、时间戳等安全参数
  3. 网络状态异常:需要处理断网、超时、弱网等场景
  4. 数据格式转换:JSON/FormData等不同格式的处理
  5. 平台差异:微信小程序与H5的差异处理

理解uni-app网络请求的底层原理和最佳实践,是构建稳定可靠应用的关键。

二、基本原理

uni-app的网络请求机制基于原生平台的网络API,通过JavaScript层封装实现跨平台支持。其核心原理如下:

  1. 请求封装:通过uni.request将请求参数转换为原生平台可识别的格式
  2. 跨平台适配:根据运行平台选择不同的网络实现(微信小程序使用wx.request,H5使用fetch)
  3. 异步处理:基于Promise的异步请求机制
  4. 数据转换:自动处理JSON格式的响应数据

关键流程:

用户触发请求 → uni.request → 平台原生网络API → 服务器响应 → 数据解析 → 回调处理

三、环境准备

  1. 开发环境:HBuilderX 3.x + Node.js 16+
  2. 服务器环境:支持CORS的Node.js服务(使用express)
  3. 配置文件:manifest.json中配置网络请求域名(微信小程序必填)
{
  "network": {
    "request": {
      "enable": true,
      "url": "https://yourdomain.com"
    }
  }
}

四、核心实现

1. 基础请求实现

// pages/index/index.vue
<template>
  <view>
    <button @click="fetchData">获取数据</button>
    <view>{{ data }}</view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      data: null
    };
  },
  methods: {
    async fetchData() {
      try {
        const res = await uni.request({
          url: 'https://yourdomain.com/api/data',
          method: 'GET'
        });
        this.data = res.data;
      } catch (err) {
        console.error('请求失败:', err);
      }
    }
  }
};
</script>

关键代码解释:

  • uni.request返回Promise对象
  • method参数指定HTTP方法(GET/POST等)
  • url需要配置到manifest.json中(微信小程序必填)
  • async/await处理异步请求

2. 带Token的请求实现

// utils/request.js
export function request(config) {
  return new Promise((resolve, reject) => {
    uni.request({
      ...config,
      header: {
        ...config.header,
        'Authorization': `Bearer ${uni.getStorageSync('token')}`
      },
      success: (res) => {
        if (res.statusCode === 200) {
          resolve(res.data);
        } else {
          reject(res);
        }
      },
      fail: (err) => {
        reject(err);
      }
    });
  });
}
// pages/index/index.vue
<template>
  <view>
    <button @click="fetchProtectedData">获取受保护数据</button>
    <view>{{ protectedData }}</view>
  </view>
</template>

<script>
import { request } from '@/utils/request';

export default {
  data() {
    return {
      protectedData: null
    };
  },
  methods: {
    async fetchProtectedData() {
      try {
        const res = await request({
          url: 'https://yourdomain.com/api/protected',
          method: 'GET'
        });
        this.protectedData = res;
      } catch (err) {
        console.error('受保护数据请求失败:', err);
      }
    }
  }
};
</script>

关键代码解释:

  • 自定义封装的request函数,统一处理Token
  • 使用uni.getStorageSync获取存储的token
  • 通过header添加Authorization头
  • 处理不同状态码的响应

3. 错误处理与重试机制

// utils/request.js
export function request(config) {
  return new Promise((resolve, reject) => {
    uni.request({
      ...config,
      header: {
        ...config.header,
        'X-Request-ID': Date.now().toString(36)
      },
      success: (res) => {
        if (res.statusCode === 200) {
          resolve(res.data);
        } else {
          reject(res);
        }
      },
      fail: (err) => {
        // 自动重试机制(最多3次)
        const retryCount = parseInt(err?.config?.retryCount || 0);
        if (retryCount < 3) {
          uni.request({
            ...config,
            retryCount: retryCount + 1
          });
        } else {
          reject(err);
        }
      }
    });
  });
}

关键代码解释:

  • 添加请求ID用于日志追踪
  • 实现自动重试机制(最多3次)
  • 在fail回调中处理网络异常
  • 通过配置参数传递重试次数

五、完整案例

登录功能实现(完整案例)

1. 服务端接口(Node.js)

// server.js
const express = require('express');
const app = express();
const port = 3000;

app.post('/api/login', (req, res) => {
  const { username, password } = req.body;
  // 模拟数据库验证
  if (username === 'admin' && password === '123456') {
    res.status(200).json({
      token: 'super-secret-token'
    });
  } else {
    res.status(401).json({ error: '认证失败' });
  }
});

app.listen(port, () => {
  console.log(`Server running at http://localhost:${port}`);
});

2. 客户端代码(uni-app)

<!-- pages/login/login.vue -->
<template>
  <view>
    <input v-model="username" placeholder="用户名" />
    <input v-model="password" type="password" placeholder="密码" />
    <button @click="login">登录</button>
    <view v-if="token">{{ token }}</view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      username: '',
      password: '',
      token: null
    };
  },
  methods: {
    async login() {
      try {
        const res = await this.$request({
          url: 'https://yourdomain.com/api/login',
          method: 'POST',
          data: {
            username: this.username,
            password: this.password
          }
        });
        uni.setStorageSync('token', res.token);
        this.token = res.token;
      } catch (err) {
        console.error('登录失败:', err);
      }
    }
  }
};
</script>

关键代码解释:

  • 使用自定义的$request封装
  • 处理登录响应并存储token
  • 使用uni.setStorageSync保存token
  • 在后续请求中自动携带token

六、源码解析

uni-app的request方法源码核心逻辑(以微信小程序为例):

// node_modules/uni-app/manifest/manifest.js
function request(options) {
  return new Promise((resolve, reject) => {
    wx.request({
      url: options.url,
      method: options.method || 'GET',
      header: {
        ...options.header,
        'X-Platform': 'wechat'
      },
      data: options.data,
      success: (res) => {
        resolve(res.data);
      },
      fail: (err) => {
        reject(err);
      }
    });
  });
}

关键点解析:

  • 自动添加平台标识头
  • 支持不同的HTTP方法
  • 自动处理响应数据
  • 提供统一的Promise接口

七、进阶使用

1. 请求拦截器

// utils/request.js
export function request(config) {
  return new Promise((resolve, reject) => {
    uni.request({
      ...config,
      header: {
        ...config.header,
        'X-Request-ID': Date.now().toString(36),
        'X-Platform': 'uni-app'
      },
      success: (res) => {
        if (res.statusCode === 200) {
          resolve(res.data);
        } else {
          reject(res);
        }
      },
      fail: (err) => {
        reject(err);
      }
    });
  });
}

2. 响应拦截器

export function request(config) {
  return new Promise((resolve, reject) => {
    uni.request({
      ...config,
      success: (res) => {
        if (res.statusCode === 200) {
          const data = res.data;
          if (data.code === 200) {
            resolve(data.data);
          } else {
            reject(data.message || '服务器错误');
          }
        } else {
          reject(res);
        }
      },
      fail: (err) => {
        reject(err);
      }
    });
  });
}

3. 基于Promise的链式调用

async function fetchData() {
  try {
    const data = await request({
      url: 'https://yourdomain.com/api/data'
    });
    console.log('获取到数据:', data);
  } catch (err) {
    console.error('请求失败:', err);
  }
}

八、性能与工程实践

1. 性能优化方案

优化策略说明实现方式
响应压缩减少传输数据量使用Gzip压缩
缓存策略减少重复请求使用uni.setStorageSync
并行请求提高请求效率使用Promise.all
资源预加载提前加载常用接口在App启动时预加载

2. 异常处理机制

export function request(config) {
  return new Promise((resolve, reject) => {
    uni.request({
      ...config,
      success: (res) => {
        if (res.statusCode === 200) {
          resolve(res.data);
        } else {
          // 记录错误日志
          uni.$log.error(`请求失败: ${res.statusCode}`);
          reject(res);
        }
      },
      fail: (err) => {
        // 记录网络错误
        uni.$log.error('网络错误:', err);
        reject(err);
      }
    });
  });
}

3. 安全加固方案

风险类型解决方案实现方式
Token泄露使用刷新Token机制存储在本地缓存并设置过期时间
明文传输使用HTTPS协议配置服务器支持HTTPS
跨域攻击配置CORS头设置Access-Control-Allow-Origin
SQL注入参数化查询使用预处理语句

九、常见问题与踩坑

1. 跨域问题解决方案

错误场景:微信小程序访问非备案域名

解决方法:

  • 配置服务器CORS头:

    res.header('Access-Control-Allow-Origin', '*');
  • 使用uni-app云开发的云函数作为代理
  • 在manifest.json中配置合法域名

2. 网络状态异常处理

错误场景:断网时请求失败

解决方法:

  • 添加网络状态检测:

    uni.getNetworkType({
      success: (res) => {
        if (res.isConnected === false) {
          uni.showToast({ title: '无网络', icon: 'none' });
        }
      }
    });
  • 实现离线缓存机制
  • 使用uni.getStorageSync存储离线数据

3. 请求参数处理问题

错误场景:FormData格式参数处理失败

解决方法:

  • 使用uni.createSelectorQuery获取表单数据
  • 使用uni.getStorageInfo获取存储数据
  • 使用uni.setStorage设置复杂数据类型
  • 使用uni.getSystemInfoSync获取设备信息

十、最佳实践

  1. 统一请求封装:创建request.js统一处理请求
  2. 错误日志记录:使用uni.$log记录请求日志
  3. Token管理:使用uni.getStorageSync安全存储
  4. 请求拦截:添加请求ID进行日志追踪
  5. 响应拦截:统一处理成功/失败状态码
  6. 性能监控:记录请求耗时进行优化
  7. 安全加固:强制使用HTTPS协议
  8. 异常处理:添加重试机制和网络状态检测
  9. 版本管理:使用uni.getSystemInfoSync获取客户端版本
  10. 接口文档:维护接口文档进行版本管理

十一、总结

uni-app的网络请求机制是连接前后端的核心桥梁,理解其工作原理和最佳实践对开发高质量应用至关重要。通过本文的深入探讨,我们掌握了:

  1. uni-app网络请求的基本原理和实现方式
  2. 多种请求场景的代码实现和关键点
  3. 实际开发中常见的问题和解决方案
  4. 性能优化和安全加固的策略
  5. 完整的请求流程和异常处理机制

在实际开发中,建议根据具体需求选择合适的请求策略。对于需要频繁请求的场景,推荐使用请求拦截器和响应拦截器进行统一管理;对于敏感数据传输,务必使用HTTPS协议并妥善管理Token;在性能敏感场景中,需要结合缓存策略和压缩技术进行优化。通过合理的设计和实现,可以构建出稳定、高效、安全的uni-app应用。

最后修改于:2026年09月28日 10:52

评论已关闭

推荐阅读

AIGC实战——Transformer模型
2024年12月01日
Socket TCP 和 UDP 编程基础(Python)
2024年11月30日
python , tcp , udp
如何使用 ChatGPT 进行学术润色?你需要这些指令
2024年12月01日
AI
最新 Python 调用 OpenAi 详细教程实现问答、图像合成、图像理解、语音合成、语音识别(详细教程)
2024年11月24日
ChatGPT 和 DALL·E 2 配合生成故事绘本
2024年12月01日
omegaconf,一个超强的 Python 库!
2024年11月24日
【视觉AIGC识别】误差特征、人脸伪造检测、其他类型假图检测
2024年12月01日
[超级详细]如何在深度学习训练模型过程中使用 GPU 加速
2024年11月29日
Python 物理引擎pymunk最完整教程
2024年11月27日
MediaPipe 人体姿态与手指关键点检测教程
2024年11月27日
深入了解 Taipy:Python 打造 Web 应用的全面教程
2024年11月26日
基于Transformer的时间序列预测模型
2024年11月25日
Python在金融大数据分析中的AI应用(股价分析、量化交易)实战
2024年11月25日
AIGC Gradio系列学习教程之Components
2024年12月01日
Python3 `asyncio` — 异步 I/O,事件循环和并发工具
2024年11月30日
llama-factory SFT系列教程:大模型在自定义数据集 LoRA 训练与部署
2024年12月01日
Python 多线程和多进程用法
2024年11月24日
Python socket详解,全网最全教程
2024年11月27日
python之plot()和subplot()画图
2024年11月26日
理解 DALL·E 2、Stable Diffusion 和 Midjourney 工作原理
2024年12月01日