在移动应用和跨平台开发中,网络请求是最基础也是最重要的功能之一。Uniapp作为一款流行的跨平台开发框架,提供了强大而灵活的网络请求API——
uni.request
。本文将全面介绍Uniapp网络请求的各个方面,包括基础使用、参数详解、错误处理、性能优化以及高级封装技巧,帮助开发者构建健壮的网络请求体系。
一、Uniapp网络请求概述
Uniapp的uni.request
是一个基于Promise风格的HTTP客户端,它封装了各平台(小程序、H5、App)的网络请求能力,提供了一致的API接口。与原生JavaScript的fetch
或jQuery的$.ajax
相比,uni.request
具有以下特点:
跨平台一致性:在不同平台上表现一致,开发者无需关心底层实现差异
简单易用:基于配置对象的API设计,学习成本低
功能全面:支持GET、POST等多种HTTP方法,可设置超时、请求头等
扩展性强:可以方便地封装和扩展,支持拦截器等高级功能
在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/json
、application/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 小程序平台
域名限制:必须在小程序后台配置合法域名
HTTPS要求:必须使用HTTPS协议
并发限制:最多同时发起10个网络请求
6.2 H5平台
跨域问题:需要后端配置CORS或使用代理
Cookie处理:与浏览器行为一致,会自动携带cookie
6.3 App平台
SSL验证:可以配置不验证SSL证书(仅开发环境使用)
本地缓存:可以使用本地缓存策略提升性能
网络状态检测:可以通过
uni.getNetworkType
获取网络类型
七、性能优化与最佳实践
合理设置缓存:对不常变的数据使用缓存减少请求
合并请求:多个相关请求可以合并为一个
取消无用请求:页面卸载时取消未完成的请求
节流与防抖:避免频繁触发相同请求
错误重试机制:对临时性错误实现自动重试
// 请求取消示例
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网络请求的各个方面,希望可以帮助开发者构建更加健壮、高效的网络请求体系。
在实际项目中,建议根据团队规范和项目需求,开发适合自己项目的请求工具库,统一处理认证、错误、日志等公共逻辑,提高开发效率和代码质量。
记住,良好的网络请求处理不仅能提升应用性能,还能显著改善用户体验,是高质量应用不可或缺的一部分。