本文档主要介绍:通过 WebIDE 或 CLI 创建云函数、安装依赖、调试云函数、部署云函数和触发云函数等步骤。
前置准备
方式1:通过 WebIDE 创建云函数
进入应用开发后台,左侧选中「低代码」菜单,开始创建一个函数。
点击函数下的「新建」按钮,填写「名称」、「API名称」字段。这里需要注意的是:
- 名称:是单纯方便开发者记忆的名字,支持中英文;
- API 名称:云函数唯一标识符,调用需要使用该名称;
- 函数类型:云函数的类型,目前支持 Node.js 和 Go;
- 长任务函数:默认不是长任务,打开表示创建长任务函数;
- 允许前端 SDK 调用:是否支持自定义组件调用,默认关闭;
- 描述:函数信息的描述说明。
注意:所有的函数代码必须放到工程的 functions 目录下,才能够能正常部署到应用中
250px|700px|reset

点击「确定」后,我们便创建了第一个云函数。效果如下图所示:
250px|700px|reset

图中功能说明如下:
- 调试:调试云函数,可以在终端中输出函数执行信息,同时也支持断点调试;
- 部署:部署云函数,可以将函数部署到云端,使流程、自定义组件、自定义 JS 事件或 OpenAPI 可以触发该函数;
- 调试配置:调试配置中可以设置 params 和 context 参数,模拟输入数据的作用;
- 依赖管理:可以安装三方依赖和升级平台依赖;
- 代码管理:支持查看当前变更详情、变更历史、拉取最新代码和撤销当前所有变更;
- 引用关系:可以查看引用当前函数的流程;
- 出入参声明:可以声明出入参,在流程调用函数时实现参数的传递;
- API 名称:支持查看「数据」中对象的 API 名称;
- 环境变量:支持查看「数据」中的全局变量信息;
方式2:本地 CLI 创建云函数
进入应用开发后台,左侧选中「低代码」->「查看工程」->「代码管理」,如下图所示:
250px|700px|reset

- 安装 CLI:本地需要配置 Node.js 环境,然后在终端中执行 npm install -g @byted-apaas/cli 安装 CLI;
- 登录租户:终端中执行 ae auth login --tenant {{tenant_name}},弹出浏览器确认授权,完成登录;
- 克隆项目:终端中执行 ae project clone {{namespace}},将代码 clone 到本地。
- 开发工具:推荐选择 Visual Studio Code 开发工具进行本地开发,目前断点调试功能仅支持该工具:
250px|700px|reset

- 操作函数的命令:终端中输入 ae function -h 可以查看所有函数相关的命令:
250px|700px|reset

- 创建函数:终端中进入项目目录,执行 ae function create {apiName} 命令创建函数 demo02JS,如下图所示:
250px|700px|reset

- 云端调试:ae function dev {apiName};
- 本地调试(支持断点):ae function debug {apiName};
注意:需要先启动调试服务器;
- 修复:如果 functions 之外的目录文件存在损坏或者智能提示存在问题,可以通过 ae function repair 尝试自动化修复;
- 安装依赖:
- Node.js 语言
- 进入 functions/nodejs 目录
- 执行命令 npm install {包名}@{包版本} 安装依赖
- Go 语言
- 进入 functions/golang 目录
- 执行命令 go get -v {包名}@{包版本} 安装依赖
- 部署:ae source push
函数列表页
「方式1」和「方式2」创建的函数,在 部署 之后,可以在「低代码」->「函数」页中看到,如下图所示:
250px|700px|reset

图中列表中字段的说明如下:
- 函数类型: 云函数的类型,目前支持 Node.js 和 Go;
- 长任务函数:长任务函数可以让函数的最大执行时间由 15 分钟延长到 3 小时;
- 状态: 当前云函数的部署状态,包括「未部署」、「已部署」。只有当状态为「已部署」时,该云函数才能在其他地方被调用。「已修改」表明当前云函数有内容修改,但未保存发布;
- 引用关系: 显示应用中引用该函数的所有业务;
- 前端 SDK 调用:是否支持自定义组件调用;
- 部署时间:最新部署的时间;
前置学习
在正式编写代码前,我们还需要了解「云函数」的编写规范及其他基础知识。
(一)函数入口
所有「云函数」都会有一个固定的函数执行入口,就像 C++ 里面 int main() 函数一样,在这里就代表「云函数」要执行的第一函数。
当然,如果你没接触过 C++ 也没关系,你只需要知道,通常意义上来说,main 函数是 C++ 程序开始后固定执行的第一个函数
在「云函数」中,函数的执行入口在代码编辑器页面即可查看到,如下图所示。针对图中的函数,开发者修改该函数内部代码即可。
250px|700px|reset

(二)云函数内置参数
云函数会提供三个固定参数,以及若干上下文对象,供开发者使用。
- params
来自云函数的入口第一个参数,主要提供以下能力:
- 表示云函数的调用入参,是由开发者在调用云函数时传入。
- context 对象
来自云函数的入口第二个参数,表示当前应用的上下文。主要提供以下能力:
- 获取租户信息
- 获取应用信息
- 获取用户信息
- 获取触发事件信息
- 用于获取上下文信息,如当前租户信息、当前 Workflow 实例信息等
- 提供简单易用的数据操作功能
- 调用全局函数
- 向aPaas 平台进行文件上传与下载
- 函数任务任务创建
- 消息中心推送消息能力
- ...
- logger 对象
来自云函数的入口第三个参数,主要提供以下能力:
- 日志输出能力,开发者可以通过该接口打印日志。日志可以在调试控制台或者「运行日志」-「函数日志」中查看
这里需要注意的是,你当然也可以使用 console 接口进行日志的打印,但使用该方法打印的日志不会保存到「运行日志」中。
至此,已经了解了「云函数」基本知识,能够正式开发一个「云函数」了。下面让我们开始吧。
正式开发
现在我们用之前提到的 方式1:WebIDE, 来创建第一个 Node.js 函数:「发送飞书消息卡片」。
下述示例代码中使用/涉及的:
- 「飞书低代码平台」 SDK 能力可参考:云函数 SDK
(一)使用 NPM 包
Node.js 的开发离不开安装依赖包。在 WebIDE 中我们可以使用 GUI 工具:「依赖管理」对依赖包进行管理。
如下图所示,通过「依赖管理」工具搜索 axios 包,并点击安装完成新增包的依赖。
250px|700px|reset

我们已经新增了对 axios 包的依赖,但若想正式使用 axios,开发者还需要主动在「云函数」中进行引入。
以实现「发送飞书消息卡片」为例:
250px|700px|reset

本例代码主要通过两步实现:
250px|700px|reset

第一步 获取飞书应用鉴权 Token
// 获取飞书应用鉴权 Token
const tenant_access_token = await getFeishuAuth(); // token 将在发送飞书消息卡片时需要,详见飞书接口文档
async function getFeishuAuth() {
const app_id = 'cli_a03d8xxxxxxx',
app_secret = '************************',
try {
const response = await axios({
method: 'post',
url: url,
headers: {
'Content-Type': 'application/json'
},
data: {
"app_id": app_id,
"app_secret": app_secret
}
});
return response.data.tenant_access_token;
}
catch (e) {
return -1;
}
}
第二步 调用飞书相关接口,实现发送飞书消息卡片
// 实现利用飞书接口发送消息(使用时请参考附录完整代码)
const response = await axios({
method: 'post',
url: url,
headers: {
'Content-Type': 'application/json; charset=utf-8',
'Authorization': `Bearer ${tenant_access_token}`
},
data: requestBody
});
(二)完成编写
最终完整的实现代码如下:
// 通过 NPM dependencies 成功安装 NPM 包后此处可引入使用
const axios = require('axios'); //
/**
* @param params 自定义参数
* @param {Context} context 上下文参数,可通过此参数下钻获取上下文变量信息
* @param {Logger} logger 日志记录器
*
* @return 函数的返回数据
*/
module.exports = async function (params, context, logger) {
// 日志功能
logger.info(`${new Date()} 函数开始执行`);
// 获取鉴权
const tenant_access_token = await getFeishuAuth();
if (tenant_access_token === -1) {
return { code: -1 };
}
// 发送飞书卡片消息
const url = '';
const requestBody = {
"email": params.borrowerEmail,
"msg_type": "interactive",
"card": {
"config": {
"wide_screen_mode": false
},
"elements": [
{
"tag": "div",
"text": {
"tag": "lark_md",
"content": "**图书馆提醒你该还书啦!**"
}
},
{
"tag": "hr"
},
{
"tag": "div",
"text": {
"tag": "lark_md",
"content": `${params.borrowerName}同学,当前你所借阅的图书《${params.bookName}》距离需归还时间还剩 **${params.remainingDays}** 天,记得要按时归还哟 :)`
}
}
]
}
};
const response = await axios({
method: 'post',
url: url,
headers: {
'Content-Type': 'application/json; charset=utf-8',
'Authorization': `Bearer ${tenant_access_token}`
},
data: requestBody
});
console.log('调用发送飞书卡片消息接口的返回', response.data)
return { code: 0 }
}
// 获取飞书应用鉴权 Token
// 此处需替换为自己的app_id 和 app_secret
async function getFeishuAuth() {
const app_id = 'cli_a03d8xxxxxxx', app_secret = '************************', url = 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/';
try {
const response = await axios({
method: 'post',
url: url,
headers: {
'Content-Type': 'application/json'
},
data: {
"app_id": app_id,
"app_secret": app_secret
}
});
return response.data.tenant_access_token;
}
catch (e) {
return -1;
}
}
(三)输入参数声明
函数需要和流程的「调用函数」节点绑定、并接受流程的变量作为入参时,需要在函数中声明输入参数。
在 WebIDE 的「出入参声明」工具中,通过点击「输入参数声明」右方的「新增入参」按钮添加参数,根据业务需要声明需要从流程中接收的输入参数。在工具中添加的参数声明会回写到函数的「index.meta.json」文件中。
在发送飞书消息的代码中,我们按照业务需要声明了 borrowerName、bookName、remainingDays、borrowerEmail 四个需要从流程变量传入的输入参数:
250px|700px|reset

声明函数入参时,需要输入以下参数变量:
- key:入参的key,在函数中通过 params.key 获取流程传递给函数的入参值
- type:入参的类型,需要和传递给函数入参的流程变量类型匹配(详细入参类型参考:附录 - 函数参数/流程变量类型对照表)
- required:入参是否必填
- label:入参的名称,在流程节点使用入参时显示该名称
- description:入参的描述
- objectApiName:入参对象的类型,当 type 为「Record」和「RecordList」时必填
250px|700px|reset

- schema:JSON 参数的结构定义,当参数类型为 JSON 时可以填入此变量,声明 JSON Schema 格式
(四)输出参数声明
流程的「调用函数」节点,在运行完成后需要把变量值返回给流程时,需要在函数中声明输出参数。
在 WebIDE 的「出入参声明」工具中,通过点击「输出参数声明」右方的「新增出参」按钮添加参数,根据业务需要声明需要从函数返回给流程的变量。
在发送飞书消息的代码中,我们按照业务需要声明了 code 作为出参返回给流程。
250px|700px|reset

函数声明了出参后,函数绑定的流程会自动在变量中创建一个同名、同类型的变量(APIName 随机生成)接收流程的出参。
调试
(一)代码调试
在正式发布代码之前,为了保证代码不会出错,「云函数」提供了在线调试能力,包括两种能力:
- 查看函数运行日志
- 模拟输入参数
注意:「调试」功能操作的是用户真实的数据,请在开发环境下进行
点击 WebIDE 右上角的「调试」,进行第一次代码调试:
250px|700px|reset

等待几秒钟,即可在 WebIDE 下方面板的「调试与运行」处,查看此次函数的运行情况:
250px|700px|reset

在本次示例中,通过日志可以发现:调用发送飞书卡片消息接口返回报错: { code: 10003, msg: 'chat_id or open_id or user_id require' }
这表明:没有传入接收方的身份 id。
查询代码发现:这里会直接取参数中的 borrowerEmail 字段,作为接收方的身份标识。
250px|700px|reset

但显然这里没有值,该如何解决?
这就涉及到调试的第二个能力——参数模拟。
(二)参数模拟
如上示例,我们需要知道不同参数情况下,函数的执行过程。
「云函数」提供的参数模拟能力,允许开发者模拟「云函数」被调用时传入的参数,通过使用模拟参数对「云函数」进行调试。
开发者可以在右侧的「调试参数」工具中,编写自己的模拟参数,如下图所示:
250px|700px|reset

在这里,模拟编写了缺少的 borrowerEmail、borrowerName、bookName、remainingDays 字段。编写完成后,再一次进行调试吧。
成功!在飞书消息中,查看到了「云函数」发出的一条飞书消息。
250px|700px|reset

至此,已经完成了第一个「云函数」的开发。
下一步,我们将函数正式发布。
部署发布
点击 WebIDE 右上方的「部署」按钮完成函数的上线流程:
等待几秒后,当函数部署完成,退出 WebIDE 回到函数列表页面:
250px|700px|reset

如果状态变成「已部署」,说明第一个函数已经完成了开发。
还差最后一步,去相应页面里面调用一下这个函数吧。
页面调用函数
以某页面的按钮调用函数为例。
在右侧配置面板的「事件」-「点击时」,选择「执行自定义JS 代码」:
250px|700px|reset

这里传入我们在创建云函数时绑定的 API 名称 和想要传入的参数。
注意需要在函数列表页面把该函数的「前端 SDK 调用」属性设置为「允许」,函数才可以被自定义事件调用
250px|700px|reset

点击「允许前端 SDK 调用」:
250px|700px|reset

点击「完成」来保存自定义 JS 代码,然后预览页面,点击按钮:
250px|700px|reset

回到飞书即可查看到消息卡片:
250px|700px|reset

流程调用函数
应用中的「借阅图书」对象管理所有借阅图书的信息。
250px|700px|reset

在「借阅图书」对象详情页通过点击按钮触发一个流程,流程获取当前「借阅图书」的数据,在「调用函数」节点绑定「给飞书发消息」函数,并把获取的借阅图书数据作为入参传给函数,函数根据入参内容动态发送飞书消息。
现在我们搭建这个简单的流程:在借阅图书对象的详情页点击按钮后触发该流程,流程把当前借阅图书记录传入流程并命名为「借阅图书」
250px|700px|reset

在「调用函数」节点绑定「给飞书发消息」函数,并把获取的借阅图书数据作为入参传给函数,函数根据入参内容动态发送飞书消息。
在调用函数节点需要完成以下配置:
- 选择「给飞书发消息」函数关联该节点;
- 设置该节点函数是否为异步执行;
- 配置函数入参和流程变量的 mapping 关系,让函数的入参能够接收流程变量的值;
250px|700px|reset

保存并启用该流程后,在借阅图书对象的详情页添加一个按钮,把按钮的点击事件配置为调用该流程,并通过页面变量把当前记录传给流程。
250px|700px|reset

预览页面并点击按钮后,回到飞书即可查看到消息卡片:
250px|700px|reset

至此,一个「云函数」的开发使用步骤全部结束。
推荐阅读
附录
函数参数/流程变量类型对照表: