云函数云对象前后端分离
# 创建云对象客户端通过importObject调用云端数据
创建云对象要在cloudfunctions里创建,cloudfunctions就是代表我们的云函数,你可以把它当场一个服务端,点击右键,新建云函数/云对象


创建成功

_before是个通用方法,只要进入云对象都会执行
我们创建一个getUser的方法,在这个云对象里是可以访问数据库的
// index.obj.js
const db = uniCloud.database()
// 云对象教程: https://uniapp.dcloud.net.cn/uniCloud/cloud-obj
// jsdoc语法提示教程:https://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/129
module.exports = {
_before: function () { // 通用预处理器
},
async getUser() {
let res = await db.collection("default").get()
return res
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
然后在demoObj上右键,点击运行本地云对象

会创建出一个demoObj.param.js文件

// demoObj.param.js
getUser()
2
然后在demoObj上右键,点击运行本地云对象,数据就请求到了

而且云对象的函数可以传参
async getUser(size=3) {
let res = await db.collection("default").limit(size).get()
return res
}
2
3
4
返回的就是三条

# 页面调用云对象
<template>
<view class="">
</view>
</template>
<script setup>
const demoObj = uniCloud.importObject("demoObj")
const getData = async () => {
let res = await demoObj.getUser()
console.log(res)
}
getData()
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 云对象使用JQL语法databaseForJQL
在客户端的时候,db.database一定会使用JQL的方式
在云对象里,如果我们想使用schema的校验,必须要用 databaseForJQL
const dbJQL = uniCloud.databaseForJQL()
module.exports = {
_before: function () { // 通用预处理器
},
async addUser(params = {}) {
let res = await dbJQL.collection("default").add(params)
console.log(res)
}
}
2
3
4
5
6
7
8
9
10
11
# JQL不支持的方法可以使用传统云函数解决
给数据库新增一条
addUser({name:'小花',age:23,like:["唱","跳"]})
现在我们要在like中插入一条'rap',JQL方法不支持,只能用传统方法
const db = uniCloud.database()
const dbCmd = db.command
const dbJQL = uniCloud.databaseForJQL()
// 云对象教程: https://uniapp.dcloud.net.cn/uniCloud/cloud-obj
// jsdoc语法提示教程:https://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/129
module.exports = {
_before: function () { // 通用预处理器
},
async updateUser(id="") {
let res = await db.collection("default").doc(id).update({
like: dbCmd.push(["rap","篮球"])
})
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
看看效果,追加成功了

# 内置特殊方法预处理_before和后处理_after
把它们当成拦截器就可以了,_before是首先去执行的,可以用它去检测登录状态,还可以定义全局的变量,在_before中定义的变量,在其他任何函数里都是可以调用的
_before: function () { // 通用预处理器
this.params = {name:"刀刀"}
this.clientInfo = this.getClientInfo() // 获取客户端信息
if(true) { // 拦截器
throw new Error("没有权限")
}
},
2
3
4
5
6
7
_after就是后处理,可以把我们返回的数据进行统一的处理
_after(error, result) {
if(error) {
throw error
}
result.auther = "刀刀"
return result
}
2
3
4
5
6
7

还可以在_before里获取当前时间,然后在_after里统计花费的时间
# 定时运行_timing
右键然后单击上传部署


点进详情,可以设置超时时间,可以定时器触发,可以云函数URL化

如果云函数需要定时/定期执行,即定时触发,您可以使用云函数定时触发器。已配置定时触发器的云函数,会在相应时间点被自动触发,函数的返回结果不会返回给调用方。
使用定时触发可以执行一些跑批任务,支付宝小程序定时触发最大超时时间为3小时,阿里云可以在使用定时触发时将云函数最高超时时间设置为600秒,腾讯云定时触发最大超时时间为900秒。
定时器触发建议在本地配置,然后上传的时候可以覆盖云端
我们先写好_timing, 功能是往数据库中随机插入一条数据
async _timing() {
let username = "匿名"+Math.random().toString().substring(3,9)
let rdmage = Math.floor(Math.random() * (50 - 10 + 1)) + 10
let res = await dbJQL.collection("default").add({
name: username,
age: rdmage
})
return res
}
2
3
4
5
6
7
8
9
# 在云对象package.json内配置定时_timing触发
打开demoObj下的package.json
其中cloudfunction-config字段是云函数配置,支持的配置如下
{
"concurrency": 10, // 单个云函数实例最大并发量,不配置的情况下默认是1
"memorySize": 512, // 函数的最大可用内存,单位MB,可选值: 128|256|512|1024|2048,默认值256,阿里云正式版默认512
"timeout": 60, // 函数的超时时间,单位秒,默认值5。阿里云最长为120秒,阿里云在定时触发时最长可以是7200秒
// triggers 字段是触发器数组,目前仅支持一个触发器,即数组只能填写一个,不可添加多个
"triggers": [{ // 阿里云腾讯云均为此形式,请阅读下方说明
// name: 触发器的名字,规则见https://uniapp.dcloud.net.cn/uniCloud/trigger,name不对阿里云生效
"name": "myTrigger",
// type: 触发器类型,目前仅支持 timer (即 定时触发器),type不对阿里云生效
"type": "timer",
// config: 触发器配置,在定时触发器下,config 格式为 cron 表达式,规则见https://uniapp.dcloud.net.cn/uniCloud/trigger。使用阿里云时会自动忽略最后一位,即代表年份的一位在阿里云不生效
"config": "0 0 2 1 * * *"
}],
// 云函数Url化path部分
"path": "",
"runtime": "", // nodejs版本,可选Nodejs8、Nodejs12、Nodejs14、Nodejs16、Nodejs18、Nodejs20
"keepRunningAfterReturn": true // 是否在云函数return之后继续执行,仅腾讯云nodejs12生效,详情见下方说明
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Cron 表达式
Cron 表达式有七个必需字段,按空格分隔。其中,每个字段都有相应的取值范围:
| 排序 | 字段 | 值 | 通配符 |
|---|---|---|---|
| 第一位 | 秒 | 0 - 59的整数 | , - * / |
| 第二位 | 分钟 | 0 - 59的整数 | , - * / |
| 第三位 | 小时 | 0 - 23的整数 | , - * / |
| 第四位 | 日 | 1 - 31的整数(需要考虑月的天数) | , - * / |
| 第五位 | 月 | 1 - 12的整数 , - * / | |
| 第六位 | 星期 | 0 - 6的整数,其中0指星期日,1指星期一,以此类推 | , - * / |
| 第七位 | 年 | 1970 - 2099的整数(阿里云和支付宝云不支持第七位) | , - * / |

如果不会配置官方下面有示例的
我们配置好package.json再上传部署一下
{
"name": "demoObj",
"dependencies": {},
"extensions": {
"uni-cloud-jql": {}
},
"cloudfunction-config": {
"memorySize": 256,
"timeout": 60,
"triggers": [{
"config": "0 * * * * * *"
}],
"path": "",
"runtime": "Nodejs18"
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
可以看到1分钟后云函数日志成功运行了一次

云数据库里也新增成功了

记住我们测试完了要快点把配置改回来再上传,不能让定时器一直跑,不然很快会把我们的免费容量用完的
# 云对象url化可以自主开发api接口
可以让云函数/云对象生成一个HTTP URL。这样非uni-app应用,可以通过ajax请求和云函数/云对象通信。
在控制台中配置path

然后写一个getUser方法
const db = uniCloud.database()
const dbCmd = db.command
const dbJQL = uniCloud.databaseForJQL()
// 云对象教程: https://uniapp.dcloud.net.cn/uniCloud/cloud-obj
// jsdoc语法提示教程:https://ask.dcloud.net.cn/docs/#//ask.dcloud.net.cn/article/129
module.exports = {
_before: function () { // 通用预处理器
},
async getUser({size=3} = params) {
if(!isNaN(size)) {
size = Number(size)
}else{
return {errMsg: "参数格式有误,需要number类型"}
}
let res = await db.collection("default").limit(size).get()
return res
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
然后在postman里访问就成功了

# 云存储内置存储
内置云存储的上传方式有3种:
- web界面:即在https://unicloud.dcloud.net.cn/ web控制台,点击云存储,通过web界面进行文件上传。该管理界面同时提供了资源浏览、删除等操作界面。
- 客户端API或组件上传:在前端js中编写uniCloud.uploadFile,或者使用uni ui的FilePicker组件,文件选择+上传均封装完毕。
- 云函数上传文件到云存储:即在云函数js中编写uniCloud.uploadFile
注意
- 前端和云函数端,均有一个相同名称的api:uniCloud.uploadFile。请不要混淆。
- 前端还有一个uni.uploadFile的API,那个API用于连接非uniCloud的上传使用。请不要混淆。
客户端API(部分)
- uploadFile(Object object) 直接上传文件到云存储。
- getTempFileURL(Object object) 在客户端把文件的fileid转换为临时URL。
云函数API(部分)
- uniCloud.uploadFile(Object uploadFileOptions) 云函数内上传文件至云存储。
- uniCloud.getTempFileURL(Object getTempFileURLOptions) 云函数获取文件下载链接。
- uniCloud.deleteFile(Object deleteFileOptions) 云函数删除云存储文件。
- uniCloud.downloadFile(Object downloadFileOptions) 云函数下载已上传至云存储的文件到云函数代码空间内。阿里云直接使用http请求url下载即可,无需使用downloadFile接口。