Uniapp网络请求全面指南:从基础到高级封装

发布于:2025-06-18 ⋅ 阅读:(27) ⋅ 点赞:(0)

在移动应用和跨平台开发中,网络请求是最基础也是最重要的功能之一。Uniapp作为一款流行的跨平台开发框架,提供了强大而灵活的网络请求API——uni.request。本文将全面介绍Uniapp网络请求的各个方面,包括基础使用、参数详解、错误处理、性能优化以及高级封装技巧,帮助开发者构建健壮的网络请求体系。

一、Uniapp网络请求概述

Uniapp的uni.request是一个基于Promise风格的HTTP客户端,它封装了各平台(小程序、H5、App)的网络请求能力,提供了一致的API接口。与原生JavaScript的fetch或jQuery的$.ajax相比,uni.request具有以下特点:

  1. 跨平台一致性:在不同平台上表现一致,开发者无需关心底层实现差异

  2. 简单易用:基于配置对象的API设计,学习成本低

  3. 功能全面:支持GET、POST等多种HTTP方法,可设置超时、请求头等

  4. 扩展性强:可以方便地封装和扩展,支持拦截器等高级功能

在Uniapp生态中,网络请求是与后端交互的主要方式,掌握uni.request的使用技巧对于开发高质量应用至关重要。

二、uni.request基础使用

2.1 基本请求示例

让我们从一个最简单的GET请求开始:

uni.request({
  url: 'https://api.example.com/data',
  success: (res) => {
    console.log('请求成功:', res.data);
  },
  fail: (err) => {
    console.error('请求失败:', err);
  }
});

这个例子展示了uni.request最基本的使用方式:传入一个配置对象,包含请求URL和成功/失败回调函数。

2.2 请求方法配置

uni.request支持所有常见的HTTP方法:

// GET请求
uni.request({
  url: 'https://api.example.com/data',
  method: 'GET'
});

// POST请求
uni.request({
  url: 'https://api.example.com/create',
  method: 'POST',
  data: { name: '产品名称', price: 99 }
});

// PUT请求
uni.request({
  url: 'https://api.example.com/update/1',
  method: 'PUT',
  data: { price: 109 }
});

// DELETE请求
uni.request({
  url: 'https://api.example.com/delete/1',
  method: 'DELETE'
});

2.3 请求参数传递

请求参数可以通过data属性传递,Uniapp会根据请求方法自动处理参数位置:

// GET请求参数会附加在URL后
uni.request({
  url: 'https://api.example.com/search',
  data: { keyword: '手机', page: 1 }
});

// POST请求参数会放在请求体中
uni.request({
  url: 'https://api.example.com/login',
  method: 'POST',
  data: { username: 'admin', password: '123456' }
});

三、请求配置详解

uni.request接受一个配置对象,包含丰富的配置选项。以下是主要配置项的详细说明:

3.1 核心配置项

配置项 类型 默认值 说明
url String - 请求地址,可以是相对路径或绝对路径
method String 'GET' HTTP方法:GET/POST/PUT/DELETE等
data Object/String/ArrayBuffer - 请求参数,根据method不同处理方式不同
header Object {'Content-Type': 'application/json'} 请求头设置
timeout Number 60000 请求超时时间,单位毫秒
dataType String 'json' 返回数据格式,可选json/text
responseType String 'text' 响应数据类型,可选text/arraybuffer

3.2 请求头设置

请求头是网络请求中非常重要的部分,常用于传递认证信息、内容类型等:

uni.request({
  url: 'https://api.example.com/protected',
  header: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer ' + token,
    'X-Custom-Header': 'custom-value'
  }
});

常见的请求头包括:

  • Content-Type: 请求体类型,如application/jsonapplication/x-www-form-urlencoded

  • Authorization: 认证令牌,通常用于JWT等认证方案

  • Accept: 告诉服务器客户端能处理的响应类型

3.3 超时设置

网络请求可能会因为各种原因超时,合理的超时设置可以提升用户体验:

uni.request({
  url: 'https://api.example.com/data',
  timeout: 10000, // 10秒超时
  success() {},
  fail(err) {
    if (err.errMsg.includes('timeout')) {
      uni.showToast({ title: '请求超时', icon: 'none' });
    }
  }
});

超时设置需要考虑业务场景:

  • 普通数据请求:5-10秒

  • 文件上传:30-60秒

  • 关键业务请求:适当延长但要有超时提示

四、响应处理与错误处理

4.1 响应数据结构

uni.request的成功回调会收到一个响应对象,包含以下属性:

{
  data: {}, // 响应数据,类型取决于dataType配置
  statusCode: 200, // HTTP状态码
  header: {}, // 响应头
  cookies: [] // 服务器返回的cookies
}

4.2 状态码处理

合理的状态码处理是健壮应用的基础:

uni.request({
  url: 'https://api.example.com/data',
  success: (res) => {
    switch (res.statusCode) {
      case 200:
        // 成功处理
        break;
      case 401:
        // 未授权,跳转登录
        uni.navigateTo({ url: '/pages/login/login' });
        break;
      case 404:
        // 资源不存在
        break;
      case 500:
        // 服务器错误
        break;
      default:
        // 其他状态码
    }
  }
});

4.3 错误处理

网络请求可能因多种原因失败,完善的错误处理必不可少:

uni.request({
  url: 'https://api.example.com/data',
  fail: (err) => {
    console.error('请求失败:', err);
    
    if (err.errMsg.includes('timeout')) {
      uni.showToast({ title: '请求超时,请重试', icon: 'none' });
    } else if (err.errMsg.includes('fail')) {
      uni.showToast({ title: '网络错误,请检查网络', icon: 'none' });
    }
  }
});

常见的错误类型包括:

  • 网络不可用

  • 请求超时

  • SSL证书错误(App端)

  • 域名未配置(小程序端)

五、高级封装与实践

5.1 Promise封装

回调方式在现代前端开发中已经不推荐使用,我们可以将uni.request封装为Promise:

function request(options) {
  return new Promise((resolve, reject) => {
    uni.request({
      ...options,
      success: (res) => {
        if (res.statusCode >= 200 && res.statusCode < 300) {
          resolve(res.data);
        } else {
          reject(new Error(`请求失败,状态码:${res.statusCode}`));
        }
      },
      fail: (err) => {
        reject(err);
      }
    });
  });
}

// 使用示例
request({
  url: 'https://api.example.com/data'
}).then(data => {
  console.log(data);
}).catch(err => {
  console.error(err);
});

5.2 完整请求封装

一个完整的请求封装通常包括以下功能:

  • 基础URL配置

  • 请求拦截(如添加token)

  • 响应拦截(如统一错误处理)

  • 请求取消

  • 请求重试

const http = {
  config: {
    baseUrl: 'https://api.example.com',
    timeout: 10000,
    header: {
      'Content-Type': 'application/json'
    }
  },
  
  interceptors: {
    request: null,
    response: null
  },
  
  request(options) {
    // 合并配置
    options = { ...this.config, ...options };
    options.url = options.baseUrl + options.url;
    
    // 请求拦截
    if (this.interceptors.request) {
      options = this.interceptors.request(options);
    }
    
    return new Promise((resolve, reject) => {
      options.success = (res) => {
        // 响应拦截
        if (this.interceptors.response) {
          res = this.interceptors.response(res);
        }
        resolve(res.data);
      };
      
      options.fail = (err) => {
        reject(err);
      };
      
      uni.request(options);
    });
  }
};

// 添加请求拦截器
http.interceptors.request = (config) => {
  const token = uni.getStorageSync('token');
  if (token) {
    config.header.Authorization = `Bearer ${token}`;
  }
  return config;
};

// 添加响应拦截器
http.interceptors.response = (response) => {
  if (response.statusCode === 401) {
    uni.navigateTo({ url: '/pages/login/login' });
    throw new Error('未授权,请重新登录');
  }
  return response;
};

// 使用示例
http.request({
  url: '/user/info',
  method: 'GET'
}).then(data => {
  console.log(data);
}).catch(err => {
  console.error(err);
});

5.3 文件上传与下载

除了普通的请求,Uniapp还提供了专门的文件上传和下载API:

// 文件上传
uni.chooseImage({
  success: (res) => {
    const tempFilePaths = res.tempFilePaths;
    uni.uploadFile({
      url: 'https://api.example.com/upload',
      filePath: tempFilePaths[0],
      name: 'file',
      formData: {
        'description': '图片描述'
      },
      success: (uploadRes) => {
        console.log(uploadRes.data);
      }
    });
  }
});

// 文件下载
uni.downloadFile({
  url: 'https://example.com/file.pdf',
  success: (res) => {
    if (res.statusCode === 200) {
      const filePath = res.tempFilePath;
      uni.openDocument({
        filePath: filePath,
        fileType: 'pdf'
      });
    }
  }
});

六、跨平台注意事项

Uniapp虽然提供了跨平台的网络请求API,但在不同平台上仍有一些差异需要注意:

6.1 小程序平台

  1. 域名限制:必须在小程序后台配置合法域名

  2. HTTPS要求:必须使用HTTPS协议

  3. 并发限制:最多同时发起10个网络请求

6.2 H5平台

  1. 跨域问题:需要后端配置CORS或使用代理

  2. Cookie处理:与浏览器行为一致,会自动携带cookie

6.3 App平台

  1. SSL验证:可以配置不验证SSL证书(仅开发环境使用)

  2. 本地缓存:可以使用本地缓存策略提升性能

  3. 网络状态检测:可以通过uni.getNetworkType获取网络类型

七、性能优化与最佳实践

  1. 合理设置缓存:对不常变的数据使用缓存减少请求

  2. 合并请求:多个相关请求可以合并为一个

  3. 取消无用请求:页面卸载时取消未完成的请求

  4. 节流与防抖:避免频繁触发相同请求

  5. 错误重试机制:对临时性错误实现自动重试

// 请求取消示例
let requestTask = uni.request({
  url: 'https://api.example.com/data',
  success() {}
});

// 在页面卸载时取消请求
onUnload() {
  requestTask.abort();
}

// 错误重试示例
function requestWithRetry(options, retry = 3) {
  return new Promise((resolve, reject) => {
    const wrappedRequest = (attempt) => {
      request(options)
        .then(resolve)
        .catch(err => {
          if (attempt < retry) {
            setTimeout(() => wrappedRequest(attempt + 1), 1000);
          } else {
            reject(err);
          }
        });
    };
    wrappedRequest(0);
  });
}

总结

Uniapp的uni.request提供了强大而灵活的网络请求能力,通过合理的封装和扩展,可以满足各种复杂的业务场景需求。本文从基础使用到高级封装,全面介绍了Uniapp网络请求的各个方面,希望可以帮助开发者构建更加健壮、高效的网络请求体系。

在实际项目中,建议根据团队规范和项目需求,开发适合自己项目的请求工具库,统一处理认证、错误、日志等公共逻辑,提高开发效率和代码质量。

记住,良好的网络请求处理不仅能提升应用性能,还能显著改善用户体验,是高质量应用不可或缺的一部分。

 


网站公告

今日签到

点亮在社区的每一天
去签到