网络请求
在 uni-app 中,网络请求是应用开发中非常重要的一部分。本文将详细介绍如何在 uni-app 中进行网络请求,包括基本用法、进阶技巧以及最佳实践。
uni.request 基础用法
uni-app 提供了统一的网络请求 API uni.request
,可以在各个平台上进行网络请求操作。
基本语法
js
uni.request({
url: 'https://api.example.com/data', // 请求的接口地址
method: 'GET', // 请求方法,可选:GET、POST、PUT、DELETE 等
data: {}, // 请求的参数
header: {}, // 设置请求的 header
success: (res) => {}, // 请求成功后的回调函数
fail: (err) => {}, // 请求失败后的回调函数
complete: () => {} // 请求完成后的回调函数(无论成功与否)
})
GET 请求示例
js
uni.request({
url: 'https://api.example.com/users',
method: 'GET',
data: {
page: 1,
limit: 10
},
header: {
'content-type': 'application/json'
},
success: (res) => {
console.log('请求成功:', res.data);
},
fail: (err) => {
console.error('请求失败:', err);
}
})
POST 请求示例
js
uni.request({
url: 'https://api.example.com/users',
method: 'POST',
data: {
username: 'test',
password: '123456'
},
header: {
'content-type': 'application/json'
},
success: (res) => {
console.log('请求成功:', res.data);
},
fail: (err) => {
console.error('请求失败:', err);
}
})
Promise 风格的网络请求
uni-app 支持使用 Promise 风格的 API,可以让代码更加简洁。
js
// Promise 方式调用
uni.request({
url: 'https://api.example.com/users',
method: 'GET'
})
.then(res => {
console.log('请求成功:', res[1].data);
})
.catch(err => {
console.error('请求失败:', err);
})
封装网络请求
在实际项目中,我们通常会对网络请求进行封装,以便统一处理请求和响应。
js
// request.js
const baseURL = 'https://api.example.com';
// 请求拦截器
const beforeRequest = (config) => {
// 添加 token
const token = uni.getStorageSync('token');
if (token) {
config.header = {
...config.header,
'Authorization': `Bearer ${token}`
};
}
return config;
};
// 响应拦截器
const handleResponse = (res) => {
// 请求成功
if (res.statusCode >= 200 && res.statusCode < 300) {
return res.data;
}
// 未授权
if (res.statusCode === 401) {
uni.showToast({
title: '登录已过期,请重新登录',
icon: 'none'
});
// 跳转到登录页
setTimeout(() => {
uni.navigateTo({
url: '/pages/login/login'
});
}, 1500);
return Promise.reject(new Error('未授权'));
}
// 其他错误
uni.showToast({
title: res.data.message || '请求失败',
icon: 'none'
});
return Promise.reject(res);
};
// 封装请求方法
const request = (options) => {
const config = beforeRequest({
...options,
url: options.url.startsWith('http') ? options.url : baseURL + options.url,
header: options.header || {
'content-type': 'application/json'
}
});
return new Promise((resolve, reject) => {
uni.request({
...config,
success: (res) => {
try {
const data = handleResponse(res);
resolve(data);
} catch (error) {
reject(error);
}
},
fail: (err) => {
uni.showToast({
title: '网络异常,请检查网络连接',
icon: 'none'
});
reject(err);
}
});
});
};
// 导出请求方法
export default {
get: (url, data, options = {}) => {
return request({
url,
data,
method: 'GET',
...options
});
},
post: (url, data, options = {}) => {
return request({
url,
data,
method: 'POST',
...options
});
},
put: (url, data, options = {}) => {
return request({
url,
data,
method: 'PUT',
...options
});
},
delete: (url, data, options = {}) => {
return request({
url,
data,
method: 'DELETE',
...options
});
}
};
使用封装后的请求方法:
js
import request from '@/utils/request';
// GET 请求
request.get('/users', { page: 1, limit: 10 })
.then(res => {
console.log('获取用户列表成功:', res);
})
.catch(err => {
console.error('获取用户列表失败:', err);
});
// POST 请求
request.post('/users', { username: 'test', password: '123456' })
.then(res => {
console.log('创建用户成功:', res);
})
.catch(err => {
console.error('创建用户失败:', err);
});
文件上传
uni-app 提供了 uni.uploadFile
方法用于文件上传。
js
uni.uploadFile({
url: 'https://api.example.com/upload',
filePath: tempFilePath,
name: 'file',
formData: {
'user': 'test'
},
success: (res) => {
console.log('上传成功:', res.data);
},
fail: (err) => {
console.error('上传失败:', err);
}
});
文件下载
uni-app 提供了 uni.downloadFile
方法用于文件下载。
js
uni.downloadFile({
url: 'https://example.com/somefile.pdf',
success: (res) => {
if (res.statusCode === 200) {
console.log('下载成功:', res.tempFilePath);
// 保存文件
uni.saveFile({
tempFilePath: res.tempFilePath,
success: (saveRes) => {
console.log('文件保存成功:', saveRes.savedFilePath);
}
});
}
},
fail: (err) => {
console.error('下载失败:', err);
}
});
网络状态监听
uni-app 提供了网络状态监听的 API,可以实时获取网络状态变化。
js
// 获取当前网络状态
uni.getNetworkType({
success: (res) => {
console.log('当前网络类型:', res.networkType);
}
});
// 监听网络状态变化
uni.onNetworkStatusChange((res) => {
console.log('网络类型:', res.networkType);
console.log('是否有网络连接:', res.isConnected);
});
WebSocket 支持
uni-app 提供了 WebSocket 相关的 API,可以实现实时通信。
js
// 创建 WebSocket 连接
const socketTask = uni.connectSocket({
url: 'wss://example.com/socket',
header: {
'content-type': 'application/json'
},
success: () => {
console.log('WebSocket 连接成功');
}
});
// 监听 WebSocket 打开
socketTask.onOpen(() => {
console.log('WebSocket 已打开');
// 发送消息
socketTask.send({
data: JSON.stringify({ type: 'login', data: { userId: '123' } }),
success: () => {
console.log('消息发送成功');
}
});
});
// 监听 WebSocket 接收消息
socketTask.onMessage((res) => {
console.log('收到服务器消息:', res.data);
});
// 监听 WebSocket 错误
socketTask.onError((res) => {
console.error('WebSocket 错误:', res);
});
// 监听 WebSocket 关闭
socketTask.onClose(() => {
console.log('WebSocket 已关闭');
});
// 关闭 WebSocket 连接
// socketTask.close();
最佳实践
1. 统一错误处理
在网络请求封装中,统一处理错误信息,避免在每个请求中重复处理。
2. 请求取消
在页面销毁时,取消未完成的请求,避免内存泄漏。
js
let requestTask = null;
// 发起请求
requestTask = uni.request({
url: 'https://api.example.com/data',
// ...其他配置
});
// 在页面 onUnload 生命周期中取消请求
onUnload() {
if (requestTask) {
requestTask.abort();
}
}
3. 请求重试
对于重要的请求,可以实现请求重试机制。
js
const requestWithRetry = (options, maxRetries = 3) => {
return new Promise((resolve, reject) => {
const attempt = (retryCount) => {
request(options)
.then(resolve)
.catch(error => {
if (retryCount < maxRetries) {
console.log(`请求失败,第 ${retryCount + 1} 次重试`);
setTimeout(() => {
attempt(retryCount + 1);
}, 1000 * Math.pow(2, retryCount)); // 指数退避策略
} else {
reject(error);
}
});
};
attempt(0);
});
};
4. 数据缓存
对于不经常变化的数据,可以实现本地缓存,减少网络请求。
js
const cachedRequest = (url, expireTime = 60 * 1000) => {
const cacheKey = `cache_${url}`;
const cacheData = uni.getStorageSync(cacheKey);
if (cacheData && cacheData.timestamp) {
const now = new Date().getTime();
if (now - cacheData.timestamp < expireTime) {
return Promise.resolve(cacheData.data);
}
}
return request.get(url).then(res => {
uni.setStorageSync(cacheKey, {
data: res,
timestamp: new Date().getTime()
});
return res;
});
};
5. 接口模块化
将接口按照业务模块进行分类,便于管理和维护。
js
// api/user.js
import request from '@/utils/request';
export default {
login: (data) => request.post('/user/login', data),
register: (data) => request.post('/user/register', data),
getUserInfo: () => request.get('/user/info'),
updateUserInfo: (data) => request.put('/user/info', data)
};
// api/product.js
import request from '@/utils/request';
export default {
getProductList: (params) => request.get('/products', params),
getProductDetail: (id) => request.get(`/products/${id}`),
createProduct: (data) => request.post('/products', data),
updateProduct: (id, data) => request.put(`/products/${id}`, data),
deleteProduct: (id) => request.delete(`/products/${id}`)
};
// 使用
import userApi from '@/api/user';
import productApi from '@/api/product';
// 登录
userApi.login({ username: 'test', password: '123456' })
.then(res => {
console.log('登录成功:', res);
});
// 获取产品列表
productApi.getProductList({ page: 1, limit: 10 })
.then(res => {
console.log('产品列表:', res);
});
跨域处理
在开发环境中,可能会遇到跨域问题。uni-app 提供了代理配置来解决跨域问题。
在项目根目录下创建 vue.config.js
文件:
js
module.exports = {
devServer: {
proxy: {
'/api': {
target: 'https://api.example.com',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
};
小程序特殊处理
在小程序中,网络请求需要配置合法域名,否则会被拦截。
- 在小程序管理后台的"开发设置"中添加服务器域名
- 在开发环境中,可以在开发工具中勾选"不校验合法域名"选项
总结
本文介绍了 uni-app 中网络请求的基本用法、进阶技巧以及最佳实践。通过合理封装和使用网络请求,可以提高代码的可维护性和可复用性,同时也能提升应用的用户体验。在实际开发中,应根据项目需求选择合适的网络请求方式和策略。