1.3 云函数与云对象的异同
1. 基本概念对比
云函数(Cloud Function)
云函数是 uniCloud 提供的一种服务端函数,它允许开发者在云端执行代码,处理业务逻辑,并返回结果给客户端。云函数是一种函数式的编程模式,每个云函数都是一个独立的函数,通过 callFunction 方法调用。
云对象(Cloud Object)
云对象是 uniCloud 提供的一种新的服务端开发模式,它允许开发者以面向对象的方式编写服务端代码,并在客户端直接调用这些对象的方法。云对象是一种面向对象的编程模式,每个云对象包含多个方法,客户端可以直接调用这些方法。
2. 文件结构对比
云函数的文件结构
一个典型的云函数包含以下文件:
- index.js:云函数的主入口文件,包含云函数的实现代码。
- package.json:云函数的配置文件,包含依赖项、版本号等信息。
- node_modules:云函数的依赖包目录。
云对象的文件结构
一个典型的云对象包含以下文件:
- index.obj.js:云对象的主入口文件,包含云对象的实现代码。
- package.json:云对象的配置文件,包含依赖项、版本号等信息。
- node_modules:云对象的依赖包目录。
3. 代码组织方式对比
云函数的代码组织
云函数通常使用 switch-case 或 if-else 结构来组织不同的功能:
// 云函数名:todo
'use strict';
exports.main = async (event, context) => {
const { method, params } = event;
switch (method) {
case 'add': {
let { title, content } = params;
title = title.trim();
content = content.trim();
if (!title || !content) {
return {
errCode: 'INVALID_TODO',
errMsg: 'TODO标题或内容不可为空'
};
}
// ...其他逻辑
return {
errCode: 0,
errMsg: '创建成功'
};
}
case 'getList': {
// 获取列表逻辑
return {
errCode: 0,
errMsg: '获取成功',
data: []
};
}
// 其他方法
default: {
return {
errCode: 'METHOD_NOT_FOUND',
errMsg: `Method[${method}] not found`
};
}
}
};
云对象的代码组织
云对象使用面向对象的方式组织代码,每个方法都是对象的一个属性:
// 云对象名:todo
module.exports = {
// 添加待办事项
async add(title, content) {
title = title.trim();
content = content.trim();
if (!title || !content) {
return {
errCode: 'INVALID_TODO',
errMsg: 'TODO标题或内容不可为空'
};
}
// ...其他逻辑
return {
errCode: 0,
errMsg: '创建成功'
};
},
// 获取待办事项列表
async getList() {
// 获取列表逻辑
return {
errCode: 0,
errMsg: '获取成功',
data: []
};
}
};
4. 调用方式对比
云函数的调用方式
客户端调用云函数需要使用 uniCloud.callFunction 方法,并传递方法名和参数:
// 调用云函数
uniCloud.callFunction({
name: 'todo',
data: {
method: 'add',
params: {
title: '标题',
content: '内容'
}
}
}).then(res => {
const { errCode, errMsg } = res.result;
if (errCode === 0) {
uni.showToast({
title: '创建成功'
});
} else {
uni.showModal({
title: '创建失败',
content: errMsg,
showCancel: false
});
}
}).catch(err => {
uni.showModal({
title: '创建失败',
content: err.errMsg,
showCancel: false
});
});
云对象的调用方式
客户端调用云对象需要使用 uniCloud.importObject 方法导入云对象,然后直接调用对象的方法:
// 导入云对象
const todo = uniCloud.importObject('todo');
// 调用云对象方法
async function addTodo() {
try {
const result = await todo.add('标题', '内容');
if (result.errCode === 0) {
uni.showToast({
title: '创建成功'
});
} else {
uni.showModal({
title: '创建失败',
content: result.errMsg,
showCancel: false
});
}
} catch (e) {
uni.showModal({
title: '创建失败',
content: e.errMsg,
showCancel: false
});
}
}
5. 特殊方法对比
云函数的特殊方法
云函数没有特殊的生命周期方法,所有逻辑都在 main 函数中处理。
云对象的特殊方法
云对象支持一些特殊的方法,这些方法以 _ 开头,用于处理云对象的生命周期和通用逻辑:
- _before:在调用云对象方法前执行,用于预处理,如参数验证、权限检查等。
- _after:在调用云对象方法后执行,用于后处理,如日志记录、结果转换等。
- _timing:定时执行的方法,用于定时任务。
// 云对象名:todo
module.exports = {
// 预处理方法
async _before() {
// 获取客户端信息
const clientInfo = this.getClientInfo();
console.log('客户端信息', clientInfo);
// 获取客户端 token
const token = this.getClientToken();
console.log('客户端 token', token);
},
// 后处理方法
async _after(result) {
// 记录日志
console.log('方法执行结果', result);
// 返回结果
return result;
},
// 定时执行的方法
async _timing() {
console.log('定时任务执行', new Date().toISOString());
// 执行定时任务
return {
errCode: 0,
errMsg: '定时任务执行成功'
};
},
// 其他方法
};
6. 交互界面对比
云函数的交互界面
云函数调用不会自动显示交互界面,需要开发者手动处理加载提示和错误处理:
// 显示加载提示
uni.showLoading({
title: '加载中...'
});
// 调用云函数
uniCloud.callFunction({
name: 'todo',
data: {
method: 'add',
params: {
title: '标题',
content: '内容'
}
}
}).then(res => {
// 隐藏加载提示
uni.hideLoading();
const { errCode, errMsg } = res.result;
if (errCode === 0) {
uni.showToast({
title: '创建成功'
});
} else {
uni.showModal({
title: '创建失败',
content: errMsg,
showCancel: false
});
}
}).catch(err => {
// 隐藏加载提示
uni.hideLoading();
uni.showModal({
title: '创建失败',
content: err.errMsg,
showCancel: false
});
});
云对象的交互界面
云对象调用默认会自动显示交互界面,包括加载提示和错误处理:
// 导入云对象
const todo = uniCloud.importObject('todo');
// 调用云对象方法,自动显示加载提示和错误处理
async function addTodo() {
try {
const result = await todo.add('标题', '内容');
if (result.errCode === 0) {
uni.showToast({
title: '创建成功'
});
}
} catch (e) {
// 错误处理由云对象自动完成
}
}
如果需要自定义交互界面,可以在导入云对象时传入配置:
// 导入云对象,自定义交互界面
const todo = uniCloud.importObject('todo', {
customUI: false, // 是否取消自动展示的交互提示界面,默认为 false
loadingOptions: { // loading 相关配置
title: '加载中...', // 显示的 loading 内的提示文字
mask: true // 是否使用透明遮罩,配置为 true 时不可点击页面其他内容
},
errorOptions: { // 错误界面相关配置
type: 'modal', // 错误信息展示方式,可取值:modal(弹框)、toast(toast 消息框)
retry: false // 是否展示重试按钮,仅在 type 为 modal 时生效
}
});
7. 类型提示对比
云函数的类型提示
云函数不支持 JSDoc 注释,无法提供类型提示。
云对象的类型提示
云对象支持 JSDoc 注释,可以提供更好的代码提示和类型检查:
// 云对象名:todo
module.exports = {
/**
* 添加待办事项
* @param {string} title 待办事项标题
* @param {string} content 待办事项内容
* @returns {object} 返回结果
*/
async add(title, content) {
// 方法实现
},
/**
* 获取待办事项列表
* @returns {object} 返回结果
*/
async getList() {
// 方法实现
}
};
8. 适用场景对比
云函数的适用场景
- 简单的业务逻辑:适用于简单的业务逻辑,如数据查询、简单的数据处理等。
- 传统的函数式编程:适用于喜欢函数式编程风格的开发者。
- 需要兼容旧版本:适用于需要兼容旧版本的场景。
云对象的适用场景
- 复杂的业务逻辑:适用于复杂的业务逻辑,如用户管理、订单处理等。
- 面向对象编程:适用于喜欢面向对象编程风格的开发者。
- 需要更好的代码组织:适用于需要更好的代码组织的场景。
- 需要更好的类型支持:适用于需要更好的类型支持的场景。
- 需要更好的错误处理:适用于需要更好的错误处理的场景。
- 需要更好的用户体验:适用于需要更好的用户体验的场景。
9. 性能对比
云函数的性能
云函数的性能取决于函数的复杂度和执行时间。由于云函数是独立的函数,每次调用都需要重新初始化,可能会有一定的冷启动时间。
云对象的性能
云对象的性能也取决于对象的复杂度和执行时间。由于云对象是面向对象的方式,可能会有更好的代码复用和缓存效果,但也可能会有更多的内存占用。
10. 开发效率对比
云函数的开发效率
云函数的开发效率相对较低,因为需要手动处理参数传递、错误处理、交互界面等。
云对象的开发效率
云对象的开发效率相对较高,因为:
- 代码更简洁:减少了样板代码,使开发更加高效。
- 更好的代码组织:面向对象的方式使代码结构更清晰,更易于维护。
- 更好的类型支持:通过 JSDoc 注释提供更好的类型提示和检查。
- 更好的错误处理:统一的错误处理机制,减少重复代码。
- 更好的用户体验:默认提供加载提示和错误处理,提升用户体验。
11. 最佳实践建议
何时使用云函数
- 简单的业务逻辑:当业务逻辑简单,不需要复杂的代码组织时,可以使用云函数。
- 需要兼容旧版本:当需要兼容旧版本时,可以使用云函数。
- 喜欢函数式编程:当喜欢函数式编程风格时,可以使用云函数。
何时使用云对象
- 复杂的业务逻辑:当业务逻辑复杂,需要更好的代码组织时,可以使用云对象。
- 需要更好的类型支持:当需要更好的类型支持时,可以使用云对象。
- 需要更好的错误处理:当需要更好的错误处理时,可以使用云对象。
- 需要更好的用户体验:当需要更好的用户体验时,可以使用云对象。
- 喜欢面向对象编程:当喜欢面向对象编程风格时,可以使用云对象。
12. 总结
云函数和云对象是 uniCloud 提供的两种不同的服务端开发模式,它们各有优缺点,适用于不同的场景。
云函数的优点
- 简单直接:函数式编程风格,简单直接。
- 兼容性好:兼容性好,可以兼容旧版本。
- 学习成本低:学习成本低,容易上手。
云函数的缺点
- 代码组织差:代码组织差,不易维护。
- 类型支持差:类型支持差,无法提供类型提示。
- 错误处理差:错误处理差,需要手动处理。
- 交互界面差:交互界面差,需要手动处理。
云对象的优点
- 代码组织好:面向对象的方式,代码组织好,易于维护。
- 类型支持好:支持 JSDoc 注释,提供更好的类型提示和检查。
- 错误处理好:统一的错误处理机制,减少重复代码。
- 交互界面好:默认提供加载提示和错误处理,提升用户体验。
- 开发效率高:开发效率高,减少样板代码。
云对象的缺点
- 学习成本高:学习成本高,需要了解面向对象编程。
- 兼容性差:兼容性差,不支持旧版本。
- 性能可能差:性能可能差,可能会有更多的内存占用。
从云对象发布后,不再推荐使用传统云函数了。如果是以数据库操作为主,则推荐使用 clientDB,开发效率是最高的。如果服务器端不操作数据库外,或者还有复杂的、不宜公开在前端的逻辑,此时推荐使用云对象。