背景和优势
20年前,restful接口开发开始流行,服务器编写接口,客户端调用接口,传输json。
现在,替代restful的新模式来了。
云对象,服务器编写API,客户端调用API,不再开发传输json的接口。思路更清晰、代码更精简。
比如服务端编写一个云对象todo,该对象有add、get、remove、update等方法。客户端的js则可以直接import这个todo云对象,直接调用add等方法。
服务器示例代码如下:
HBuilderX中在uniCloud/cloudfunctions目录新建云函数,选择类型为云对象,起名为unicloudObjTest。打开云对象入口index.obj.js,添加一个add方法。
// 云对象名:todo
module.exports = {
add(title, content) {
title = title.trim()
content = content.trim()
if(!title || !content) {
return {
errCode: 'INVALID_TODO',
errMsg: 'TODO标题或内容不可为空'
}
}
// ...其他逻辑
return {
errCode: 0,
errMsg: '创建成功'
}
}
}
然后在客户端的js中,import这个todo对象,调用它的add方法
const todo = uniCloud.importObject('todo') //第一步导入云对象
async function addTodo () {
try {
const res = await todo.add('title demo', 'content demo') //导入云对象后就可以直接调用该对象的方法了,注意使用异步await
uni.showToast({
title: '创建成功'
})
} catch (e) {
// 符合uniCloud响应体规范 https://uniapp.dcloud.net.cn/uniCloud/cf-functions?id=resformat,自动抛出此错误
uni.showModal({
title: '创建失败',
content: e.errMsg,
showCancel: false
})
}
}
可以看到云对象的代码非常清晰,代码行数也只有33行。
而同样的逻辑,使用传统的接口方式则需要更多代码,见下:
// 传统方式调用云函数-云函数代码
// 云函数名:todo
// 云函数入口index.js内容如下
'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: '创建成功'
}
}
}
return {
errCode: 'METHOD_NOT_FOUND',
errMsg: `Method[${method}] not found`
}
};
// 传统方式调用云函数-客户端代码
async function addToDo () {
try {
const res = await uniCloud.callFunction({
name: 'todo',
data: {
method: 'add',
params: {
title: 'title demo',
content: 'content demo'
}
}
})
const {
errCode,
errMsg
} = res.result
if(errCode) {
uni.showModal({
title: '创建失败',
content: errMsg,
showCancel: false
})
return
}
uni.showToast({
title: '创建成功'
})
} catch (e) {
uni.showModal({
title: '创建失败',
content: e.message,
showCancel: false
})
}
}
以上传统开发需要68行代码,对比云对象的33行代码,不但工作量大,而且逻辑也不如云对象清晰。
_注:以上例子仅用于方便初学者理解。实际开发中对于简单的数据库操作,使用clientDB在前端直接操作数据库是更简单、代码更少的方案,都不需要写云端代码。
总结下云对象带来的好处:
- 更清晰的逻辑
- 更精简的代码
- 更少的协作成本(以及矛盾~)
- 客户端调用时在ide里有完善的代码提示,方法参数均可提示。(传输json可没法在ide里提示)
- 默认支持uniCloud响应体规范,方便错误拦截和统一处理
示例如下
创建云对象
云对象,其实是对云函数的封装。和创建云函数一样,在uniCloud/cloudfunctions目录右键新建云函数,选择云对象类型,输入云对象名称创建云对象,此处以云对象unicloudObjTest为例,创建的云对象包含一个index.obj.js。
创建之后的云函数结构如下
默认云对象模板是不包含任何方法的,我们为此对象添加一个add方法作为示例。
module.exports = {
add: function(title = '', content = '') {
title = title.trim()
content = content.trim()
if(!title || !content) {
return {
errCode: 'INVALID_TODO',
errMsg: 'TODO标题或内容不可为空'
}
}
// ...其他逻辑,如操作todo数据表添加数据
return {
errCode: 0,
errMsg: '创建成功'
}
}
}
至此云对象todo已经有了一个可以访问的方法了。接下来看如何使用客户端调用此云对象内的方法
客户端调用云对象
客户端通过uniCloud.importObject方法获取云对象的实例,并可以通过此实例调用云对象内的方法。用法如下
const todo = uniCloud.importObject('unicloudObjTest')
const res = await todo.add('title demo', 'content demo')
云对象的API
云对象作为云函数的一种,可以调用所有node的API和uniCloud的API。
除上述API之外,云对象的this对象还有一批专用方法来获取当前请求的上下文信息。
与云函数入参时的context不同,云对象没有context。它通过this对象挂载的几个内置方法来获取上下文信息。请注意开发者避免在this上挂载同名方法