前端与云服务交互
在uniCloud开发中,前端与云服务的交互是实现应用功能的关键环节。本文将详细介绍前端如何与uniCloud的云函数、云对象、云数据库和云存储进行交互,帮助开发者构建完整的前后端应用。
1. 前端与云服务交互概述
1.1 交互方式
uniCloud提供了多种前端与云服务交互的方式:
- 云函数调用:通过
uniCloud.callFunction方法调用云函数 - 云对象调用:通过
uniCloud.importObject方法调用云对象 - 云数据库操作:通过
uniCloud.database方法操作云数据库 - 云存储操作:通过
uniCloud.uploadFile、uniCloud.downloadFile等方法操作云存储
1.2 交互流程
前端与云服务交互的基本流程如下:
- 初始化:前端初始化uniCloud环境
- 请求:前端发送请求到云服务
- 处理:云服务处理请求并返回结果
- 响应:前端接收并处理响应结果
1.3 交互特点
uniCloud前端与云服务交互具有以下特点:
- 简单易用:提供统一的API,简化交互过程
- 类型安全:支持TypeScript,提供类型提示和检查
- 自动处理:自动处理请求和响应的序列化和反序列化
- 错误处理:提供统一的错误处理机制
- 权限控制:支持基于用户身份的权限控制
2. 云函数调用
2.1 基本调用
// 调用云函数
uniCloud.callFunction({
name: 'function-name', // 云函数名称
data: { // 传递给云函数的参数
param1: 'value1',
param2: 'value2'
},
success: function(res) { // 成功回调
console.log(res.result); // 云函数返回的结果
},
fail: function(err) { // 失败回调
console.error(err); // 错误信息
}
});
2.2 异步调用
// 使用async/await调用云函数
async function callCloudFunction() {
try {
const res = await uniCloud.callFunction({
name: 'function-name',
data: {
param1: 'value1',
param2: 'value2'
}
});
console.log(res.result); // 云函数返回的结果
} catch (err) {
console.error(err); // 错误信息
}
}
2.3 带UI交互的调用
// 带UI交互的云函数调用
uni.showLoading({
title: '加载中...'
});
uniCloud.callFunction({
name: 'function-name',
data: {
param1: 'value1',
param2: 'value2'
},
success: function(res) {
uni.hideLoading();
console.log(res.result);
},
fail: function(err) {
uni.hideLoading();
uni.showToast({
title: '操作失败',
icon: 'none'
});
console.error(err);
}
});
2.4 批量调用
// 批量调用云函数
async function batchCallFunctions() {
try {
const results = await Promise.all([
uniCloud.callFunction({
name: 'function1',
data: { param1: 'value1' }
}),
uniCloud.callFunction({
name: 'function2',
data: { param2: 'value2' }
}),
uniCloud.callFunction({
name: 'function3',
data: { param3: 'value3' }
})
]);
console.log(results); // 所有云函数返回的结果
} catch (err) {
console.error(err);
}
}
3. 云对象调用
3.1 基本调用
// 调用云对象
const userObj = uniCloud.importObject('user');
userObj.getUserInfo({
userId: 'user-id'
}).then(res => {
console.log(res); // 云对象返回的结果
}).catch(err => {
console.error(err); // 错误信息
});
3.2 异步调用
// 使用async/await调用云对象
async function callCloudObject() {
try {
const userObj = uniCloud.importObject('user');
const res = await userObj.getUserInfo({
userId: 'user-id'
});
console.log(res); // 云对象返回的结果
} catch (err) {
console.error(err); // 错误信息
}
}
3.3 带UI交互的调用
// 带UI交互的云对象调用
async function callCloudObjectWithUI() {
uni.showLoading({
title: '加载中...'
});
try {
const userObj = uniCloud.importObject('user');
const res = await userObj.getUserInfo({
userId: 'user-id'
});
uni.hideLoading();
console.log(res);
} catch (err) {
uni.hideLoading();
uni.showToast({
title: '获取用户信息失败',
icon: 'none'
});
console.error(err);
}
}
3.4 调用多个方法
// 调用云对象的多个方法
async function callMultipleMethods() {
try {
const userObj = uniCloud.importObject('user');
// 调用多个方法
const [userInfo, userOrders, userSettings] = await Promise.all([
userObj.getUserInfo({ userId: 'user-id' }),
userObj.getUserOrders({ userId: 'user-id' }),
userObj.getUserSettings({ userId: 'user-id' })
]);
console.log(userInfo, userOrders, userSettings);
} catch (err) {
console.error(err);
}
}
4. 云数据库操作
4.1 获取数据库实例
// 获取数据库实例
const db = uniCloud.database();
4.2 添加数据
// 添加单条数据
db.collection('collection-name').add({
field1: 'value1',
field2: 'value2',
createTime: Date.now()
}).then(res => {
console.log(res.id); // 新增数据的ID
}).catch(err => {
console.error(err);
});
// 添加多条数据
db.collection('collection-name').add([
{
field1: 'value1',
field2: 'value2',
createTime: Date.now()
},
{
field1: 'value3',
field2: 'value4',
createTime: Date.now()
}
]).then(res => {
console.log(res.ids); // 新增数据的ID数组
}).catch(err => {
console.error(err);
});
4.3 查询数据
// 查询单条数据
db.collection('collection-name').doc('document-id').get().then(res => {
console.log(res.data); // 查询结果
}).catch(err => {
console.error(err);
});
// 查询多条数据
db.collection('collection-name')
.where({
field1: 'value1',
field2: db.command.gt(100)
})
.field({
field1: true,
field2: true
})
.orderBy('field2', 'desc')
.skip(0)
.limit(10)
.get()
.then(res => {
console.log(res.data); // 查询结果
})
.catch(err => {
console.error(err);
});
4.4 更新数据
// 更新单条数据
db.collection('collection-name').doc('document-id').update({
field1: 'new-value',
updateTime: Date.now()
}).then(res => {
console.log(res.updated); // 更新的数据数量
}).catch(err => {
console.error(err);
});
// 更新多条数据
db.collection('collection-name')
.where({
field1: 'value1'
})
.update({
field2: 'new-value',
updateTime: Date.now()
})
.then(res => {
console.log(res.updated); // 更新的数据数量
})
.catch(err => {
console.error(err);
});
4.5 删除数据
// 删除单条数据
db.collection('collection-name').doc('document-id').remove().then(res => {
console.log(res.deleted); // 删除的数据数量
}).catch(err => {
console.error(err);
});
// 删除多条数据
db.collection('collection-name')
.where({
field1: 'value1'
})
.remove()
.then(res => {
console.log(res.deleted); // 删除的数据数量
})
.catch(err => {
console.error(err);
});
4.6 聚合操作
// 聚合操作
db.collection('collection-name')
.aggregate()
.match({
field1: 'value1'
})
.group({
_id: '$field2',
count: db.command.aggregate.count(),
sum: db.command.aggregate.sum('$field3')
})
.sort({
count: -1
})
.limit(10)
.end()
.then(res => {
console.log(res.data); // 聚合结果
})
.catch(err => {
console.error(err);
});
5. 云存储操作
5.1 上传文件
// 上传单个文件
uni.chooseImage({
count: 1,
success: function(res) {
const tempFilePath = res.tempFilePaths[0];
uniCloud.uploadFile({
filePath: tempFilePath,
cloudPath: 'folder/file-name.jpg',
onUploadProgress: function(progressEvent) {
console.log(progressEvent); // 上传进度
},
success: function(res) {
console.log(res.fileID); // 文件ID
},
fail: function(err) {
console.error(err);
}
});
}
});
// 上传多个文件
uni.chooseImage({
count: 9,
success: function(res) {
const tempFilePaths = res.tempFilePaths;
const fileList = tempFilePaths.map((filePath, index) => {
return {
filePath: filePath,
cloudPath: `folder/file-name-${index}.jpg`
};
});
uniCloud.uploadFile({
fileList: fileList,
onUploadProgress: function(progressEvent) {
console.log(progressEvent); // 上传进度
},
success: function(res) {
console.log(res.fileList); // 文件ID列表
},
fail: function(err) {
console.error(err);
}
});
}
});
5.2 下载文件
// 下载单个文件
uniCloud.downloadFile({
fileID: 'cloud://space-id.folder/file-name.jpg',
onDownloadProgress: function(progressEvent) {
console.log(progressEvent); // 下载进度
},
success: function(res) {
console.log(res.tempFilePath); // 临时文件路径
},
fail: function(err) {
console.error(err);
}
});
// 下载多个文件
uniCloud.downloadFile({
fileList: [
'cloud://space-id.folder/file-name-1.jpg',
'cloud://space-id.folder/file-name-2.jpg'
],
onDownloadProgress: function(progressEvent) {
console.log(progressEvent); // 下载进度
},
success: function(res) {
console.log(res.fileList); // 临时文件路径列表
},
fail: function(err) {
console.error(err);
}
});
5.3 删除文件
// 删除单个文件
uniCloud.deleteFile({
fileList: ['cloud://space-id.folder/file-name.jpg'],
success: function(res) {
console.log(res.fileList); // 删除成功的文件ID列表
},
fail: function(err) {
console.error(err);
}
});
// 删除多个文件
uniCloud.deleteFile({
fileList: [
'cloud://space-id.folder/file-name-1.jpg',
'cloud://space-id.folder/file-name-2.jpg'
],
success: function(res) {
console.log(res.fileList); // 删除成功的文件ID列表
},
fail: function(err) {
console.error(err);
}
});
5.4 获取文件信息
// 获取文件信息
uniCloud.getTempFileURL({
fileList: ['cloud://space-id.folder/file-name.jpg'],
success: function(res) {
console.log(res.fileList); // 文件信息列表,包含临时访问链接
},
fail: function(err) {
console.error(err);
}
});
6. 前端与云服务交互的最佳实践
6.1 错误处理
// 统一的错误处理
function handleError(err) {
console.error(err);
// 根据错误类型显示不同的提示
if (err.code === 'TOKEN_EXPIRED') {
uni.showToast({
title: '登录已过期,请重新登录',
icon: 'none'
});
// 跳转到登录页
uni.navigateTo({
url: '/pages/login/login'
});
} else if (err.code === 'PERMISSION_DENIED') {
uni.showToast({
title: '没有权限执行此操作',
icon: 'none'
});
} else {
uni.showToast({
title: '操作失败,请稍后重试',
icon: 'none'
});
}
}
// 使用统一的错误处理
async function callCloudFunction() {
try {
const res = await uniCloud.callFunction({
name: 'function-name',
data: {
param1: 'value1'
}
});
console.log(res.result);
} catch (err) {
handleError(err);
}
}
6.2 请求封装
// 封装云函数调用
function callFunction(name, data = {}) {
return new Promise((resolve, reject) => {
uniCloud.callFunction({
name: name,
data: data,
success: function(res) {
resolve(res.result);
},
fail: function(err) {
reject(err);
}
});
});
}
// 使用封装的云函数调用
async function getUserInfo(userId) {
try {
const result = await callFunction('getUserInfo', { userId });
return result;
} catch (err) {
handleError(err);
return null;
}
}
6.3 数据缓存
// 数据缓存
const cache = {
data: {},
timeout: 5 * 60 * 1000, // 缓存过期时间,默认5分钟
// 设置缓存
set(key, value, timeout = this.timeout) {
this.data[key] = {
value: value,
expire: Date.now() + timeout
};
},
// 获取缓存
get(key) {
if (!this.data[key]) {
return null;
}
if (Date.now() > this.data[key].expire) {
delete this.data[key];
return null;
}
return this.data[key].value;
},
// 清除缓存
clear(key) {
if (key) {
delete this.data[key];
} else {
this.data = {};
}
}
};
// 使用缓存
async function getUserInfoWithCache(userId) {
const cacheKey = `user_${userId}`;
const cachedData = cache.get(cacheKey);
if (cachedData) {
return cachedData;
}
try {
const result = await callFunction('getUserInfo', { userId });
cache.set(cacheKey, result);
return result;
} catch (err) {
handleError(err);
return null;
}
}
6.4 请求队列
// 请求队列
class RequestQueue {
constructor() {
this.queue = [];
this.running = false;
}
// 添加请求
add(request) {
return new Promise((resolve, reject) => {
this.queue.push({
request,
resolve,
reject
});
this.run();
});
}
// 执行请求
async run() {
if (this.running || this.queue.length === 0) {
return;
}
this.running = true;
while (this.queue.length > 0) {
const { request, resolve, reject } = this.queue.shift();
try {
const result = await request();
resolve(result);
} catch (err) {
reject(err);
}
}
this.running = false;
}
}
// 创建请求队列
const requestQueue = new RequestQueue();
// 使用请求队列
function callFunctionWithQueue(name, data = {}) {
return requestQueue.add(() => {
return callFunction(name, data);
});
}
6.5 请求重试
// 请求重试
async function callFunctionWithRetry(name, data = {}, maxRetries = 3) {
let retries = 0;
while (retries < maxRetries) {
try {
return await callFunction(name, data);
} catch (err) {
retries++;
if (retries === maxRetries) {
throw err;
}
// 等待一段时间后重试
await new Promise(resolve => setTimeout(resolve, 1000 * retries));
}
}
}
7. 前端与云服务交互的常见问题
7.1 跨域问题
uniCloud前端与云服务交互不存在跨域问题,因为uniCloud已经处理了跨域请求。
7.2 网络问题
// 处理网络问题
async function callFunctionWithNetworkCheck(name, data = {}) {
// 检查网络状态
const networkType = await new Promise(resolve => {
uni.getNetworkType({
success: function(res) {
resolve(res.networkType);
},
fail: function() {
resolve('unknown');
}
});
});
if (networkType === 'none') {
uni.showToast({
title: '网络连接不可用,请检查网络设置',
icon: 'none'
});
return null;
}
try {
return await callFunction(name, data);
} catch (err) {
if (err.code === 'NETWORK_ERROR') {
uni.showToast({
title: '网络请求失败,请稍后重试',
icon: 'none'
});
} else {
handleError(err);
}
return null;
}
}
7.3 超时问题
// 处理超时问题
function callFunctionWithTimeout(name, data = {}, timeout = 10000) {
return new Promise((resolve, reject) => {
const timeoutId = setTimeout(() => {
reject(new Error('请求超时'));
}, timeout);
uniCloud.callFunction({
name: name,
data: data,
success: function(res) {
clearTimeout(timeoutId);
resolve(res.result);
},
fail: function(err) {
clearTimeout(timeoutId);
reject(err);
}
});
});
}
7.4 并发问题
// 处理并发问题
const requestMap = new Map();
function callFunctionWithConcurrencyControl(name, data = {}, key = null) {
// 如果没有提供key,则使用name和data的组合作为key
if (!key) {
key = `${name}_${JSON.stringify(data)}`;
}
// 如果已经有相同的请求在进行中,则返回该请求的Promise
if (requestMap.has(key)) {
return requestMap.get(key);
}
// 创建新的请求
const promise = callFunction(name, data).finally(() => {
// 请求完成后,从Map中移除
requestMap.delete(key);
});
// 将请求添加到Map中
requestMap.set(key, promise);
return promise;
}
8. 总结
前端与云服务交互是uniCloud应用开发的核心环节,通过本文的介绍,您应该已经了解了前端如何与uniCloud的云函数、云对象、云数据库和云存储进行交互。在实际开发中,根据业务需求,合理使用这些交互方式,可以构建高效、可靠的前后端应用。
同时,本文还提供了一些最佳实践和常见问题的解决方案,可以帮助您更好地处理前端与云服务交互中的各种情况。希望这些内容对您的uniCloud开发有所帮助。