简介
云函数是运行在云端的 JavaScript 代码,是基于 Node.js 的扩展。
在常规的 Node API 基础上,uniCloud的云函数环境内置了uniCloud对象,这个对象内置了网络、数据库等各种API。
每个云函数是一个js包,在云函数被调用时,由 serverless 调度系统分配硬件资源启动一个 node 环境来运行这个云函数。
每个云函数是一个目录,其中普通云函数有index.js入口文件,云对象的入口文件则是index.obj.js。
云函数启动后实例会保留一段时间(如15分钟),超过保留期后若该云函数一直没有被再调用,那这个实例会被释放。所以云函数有冷启动的概念。
注意事项
- 云函数内使用commonjs规范,不可使用import、export
- 不同项目使用同一个服务空间时,不可使用同名云函数。同名云函数会相互覆盖。
- 在HBuilderX创建云函数时,如果新云函数与服务器上已存在同名云函数,会用新函数覆盖。所以应先选择从服务空间下载云函数。
- 单个云函数大小限制为10M(包含node_modules),过大的云函数影响运行性能,也会增加计费的gbs。同时腾讯云支持在云端安装node_modules,此时不占用云函数体积。
- uniCloud的阿里云版,暂不可使用相对路径读取文件(比如fs.readFileSync('./info.txt')),可以使用绝对路径fs.readFileSync(path.resolve(__dirname,'./info.txt'))
云函数分类
云函数有若干子概念,包括 普通云函数、云对象、公共模块、clientDB的action云函数、uniCloud扩展库。
- 普通云函数:通过传统json接口方式和客户端通信,客户端使用
uniCloud.callfunction("")
调用云函数 - 云对象:是通过前端导入对象来操作的,客户端使用
uniCloud.importObject("")
导入云对象。详见云对象 - 公共模块:用于不同的云函数/云对象,抽取和共享相同代码
- action云函数(不推荐使用):为了弥补clientDB客户端直接操作数据库的局限而设计的,从HBuilderX 3.6.11开始,推荐使用数据库触发器替代action云函数。
- uniCloud扩展库:为了裁剪和控制云函数体积而设计的,一些不太常用的功能比如Redis,独立为可选扩展库,避免增大每个云函数的体积
客户端和云函数的通信
uniCloud体系里,客户端和服务端的云函数通信,有4种方式:
clientDB针对的场景是数据库操作,它优化了可以不写或少写服务器代码
云对象针对的场景是非数据库操作或不宜前端暴露的数据库操作时,和uni-app客户端的通信方式。它优化了代码结构,更精简、简单
uniCloud API列表
云函数支持 js 和 nodejs 的标准API,如console.log()、setTimeout(),除了标准API外,云函数环境中内置了uniCloud对象,扩展了一批新API,实际开发中更常用的是uniCloud的扩展API。见下:
扩展库
开发者可以对云函数目录点右键,管理公共模块和扩展库依赖,在其中选择要加载的扩展库。这个可视化界面对应的数据在云函数目录下的 package.json 内的extensions字段下。
目前支持的扩展库如下
○ JQL扩展库[uni-cloud-jql]:用于在云函数内使用JQL语法操作数据库
○ redis扩展库[uni-cloud-redis]:云函数内使用redis
○ 发送短信扩展[uni-cloud-sms]:云函数中发送短信
○ 一键登录API扩展[uni-cloud-verify]:手机App调用运营商一键登录服务时,云函数中获取到真实手机号
○ 统一推送服务扩展库[uni-cloud-push]:云函数内使用uni-push
比如:开启了redis扩展库的云函数package.json示例
{
"name": "add-article",
"version": "1.0.0",
"description": "新增文章",
"main": "index.js",
"extensions": {
"uni-cloud-redis": {} // 配置为空对象即可,后续如有扩展参数会在此处配置
}
}
公共模块
云函数支持公共模块。多个云函数/云对象的共享部分,可以抽离为公共模块,然后被多个云函数引用。
创建并引入公用模块
在uniCloud/cloudfunctions/common右键新建公共模块(本例中为hello-common),会自动创建入口index.js文件和package.json文件。
// common/hello-common/index.js
function getVersion() {
return '0.0.1'
}
module.exports = {
getVersion,
secret: 'your secret'
}
在hello-common右键上传公共模块到云端。
在要引入共用模块的云函数/云对象目录(本例为use-common)右键管理本云函数的扩展库/公共模块依赖,选择需要的公共模块确定。
// use-common/index.js
'use strict';
const {
secret,
getVersion
} = require('hello-common')
exports.main = async (event, context) => {
let version = getVersion()
return {
secret,
version
}
}
云函数/云对象中使用jql
HBuilderX 3.4起,新建云函数/云对象,默认加载uni-cloud-jql
扩展库。
使用uniCloud.databaseForJQL
方法,可以得到一个JQL数据库操作对象。
云函数中使用
exports.main = async (event, context) => {
const dbJQL = uniCloud.databaseForJQL({ // 获取JQL database引用,此处需要传入云函数的event和context,必传
event,
context
})
const bookQueryRes = await dbJQL.collection('book').where("name=='三国演义'").get() // 直接执行数据库操作
return {
bookQueryRes
}
};
云对象中使用
云对象中无法获取event和context,为方便在云对象中使用jql扩展,自HBuilderX 3.4.10起,uniCloud.databaseForJQL方法接收云对象clientInfo作为参数
module.exports = {
addTodo (title, content) {
const dbJQL = uniCloud.databaseForJQL({ // 获取JQL database引用,此处需要传入云对象的clientInfo
clientInfo: this.getClientInfo()
})
}
}
与clientDB的差异
虽然都使用 JQL,但云端和客户端还是有一点区别
clientDB无论如何不可访问password类型字段,不管schema的权限如何,这类数据不传输到客户端。云函数内可以访问password类型字段,但受schema配置的权限约束。
clientDB有action云函数的概念,为了弥补客户端操作数据库的不足。云函数没有再使用action的必要了。