Skip to Content
帮助文档开发者集成运行代码节点开发

运行代码节点开发

运行代码是行为流中的后端代码扩展节点。开发者可以在受限的 JavaScript 运行环境中处理数据、执行 GraphQL、调用 API 和行为流,并将结果传递给后续节点。

当现有节点无法直接表达所需逻辑时,再使用运行代码。数据库操作、API 调用和行为流调用如果可以通过专用节点完成,优先使用对应节点,便于配置、维护和排错。

开发流程

添加节点

在行为流中添加 运行代码,选中节点后在右侧编辑器中编写 JavaScript。需要更大编辑区域时,可以展开代码编辑器。

声明输入

在节点的输入配置中添加代码需要使用的参数,并绑定行为流输入、前序节点结果或其他数据。

在代码中通过 context.getArg() 按名称读取:

const quantity = context.getArg('quantity'); const unitPrice = context.getArg('unitPrice');

参数名称必须与节点中声明的输入完全一致。

声明输出

在节点的输出配置中添加需要传给后续节点的字段,并选择对应类型。在代码中通过 context.setReturn() 设置结果:

const total = quantity * unitPrice; context.setReturn('total', total);

输出名称和类型必须与节点配置一致。没有声明的返回值不会成为下游节点可以绑定的结果。

测试节点

为输入提供测试值后运行节点,检查输出结果和运行日志。确认节点本身正确后,再测试包含下游节点的完整行为流。

最小完整示例

以下代码读取订单数量和单价,校验输入并返回总价:

const quantity = context.getArg('quantity'); const unitPrice = context.getArg('unitPrice'); if (typeof quantity !== 'number' || quantity <= 0) { context.error('quantity must be greater than 0'); throw new Error('Invalid quantity'); } const total = quantity * unitPrice; context.log('Calculated total:', total); context.setReturn('total', total);

该节点需要声明两个数字输入 quantityunitPrice,以及一个数字输出 total

运行环境

代码在 Zion 后端的 JavaScript 沙箱中同步执行。它不是浏览器环境,也不是完整的 Node.js 环境。

限制说明
同步执行不支持 asyncawaitPromise。Context API 也会阻塞并直接返回结果。
不支持模块不能使用 importrequire 或动态加载第三方包。
不支持浏览器 API不能使用 windowdocumentlocalStoragealert 等对象。
不支持直接网络请求不能使用 fetchXMLHttpRequest;应调用已配置的 API 或使用 runGql
不支持文件系统不能访问 fs、服务器目录或其他本地文件。
不支持定时器不能使用 setTimeoutsetInterval 等异步调度能力。
使用专用日志使用 context.log()context.error(),不要依赖 console.log()

节点运行时间受行为流执行模式、项目版本和全局生命周期限制,详见搭建行为流 - 超时策略

Context API

运行环境通过全局 context 对象提供输入、输出、日志和后端服务调用能力。编辑器中的 代码工具 列表会显示当前可用方法。

输入、输出和日志

方法返回值说明
context.getArg(name)any读取节点已声明的输入。
context.setReturn(name, value)void设置节点已声明的输出。
context.log(...values)void写入普通运行日志。
context.error(...values)void写入错误级别运行日志。

context.error() 只记录日志,不会自动终止节点。需要让节点失败时,应显式抛出异常。

数据与服务调用

runGql

执行项目 Runtime API 中的 GraphQL Query 或 Mutation:

context.runGql( operationName: string, gql: string, variables: Record<string, any>, permission: { role: string } ): any
  • operationName 必须与 GraphQL 文本中的 Operation 名称一致。
  • 没有变量时传入空对象 {}
  • permission 固定使用 { role: 'admin' }
  • 返回 GraphQL 响应中的 data 对象;执行失败时节点抛出错误。

在 Zion 编辑器中打开 开发者接入 → GraphiQL,可以查看当前项目的 Schema 并调试 Operation。数据模型发生变化后,应先同步变更或发布,再刷新 Schema。

const orderId = context.getArg('orderId'); const gql = `query GetOrder($id: bigint!) { order_by_pk(id: $id) { id status total } }`; const result = context.runGql( 'GetOrder', gql, { id: orderId }, { role: 'admin' } ); if (!result.order_by_pk) { throw new Error('Order not found'); } context.setReturn('order', result.order_by_pk);

数据库字段和 GraphQL 语法参阅 Runtime API 参考

callThirdPartyApi

调用项目中已经配置的第三方 API:

context.callThirdPartyApi( operationId: string, args: Record<string, any> ): { code: number; data: any }

operationId 和参数名称必须与 API 配置一致。返回后先检查 HTTP 状态码,再读取响应数据:

const response = context.callThirdPartyApi('get_shipping_quote', { fz_body: { postcode: context.getArg('postcode'), }, }); if (response.code < 200 || response.code >= 300) { context.error('API request failed:', JSON.stringify(response)); throw new Error('Shipping API request failed'); } context.setReturn('price', response.data.price);

callActionFlow

同步调用另一个同步行为流,并等待其执行完成:

context.callActionFlow( actionFlowId: string, versionId: number | null, args: Record<string, any> ): any

返回目标行为流声明的输出。第二个参数是为兼容早期接口保留的版本参数;调用时固定传入 null,不需要指定行为流版本。

const result = context.callActionFlow( '8a76458b-3572-48c3-ae54-b478286eac61', null, { orderId: context.getArg('orderId') } ); context.setReturn('status', result.status);

callActionFlow 只能调用同步行为流。异步行为流使用 createActionFlowTask

createActionFlowTask

创建异步行为流任务:

context.createActionFlowTask( actionFlowId: string, versionId: number | null, args: Record<string, any> ): number

第二个参数同样固定传入 null。该方法立即返回任务 ID,不会返回目标行为流的最终输出:

const taskId = context.createActionFlowTask( 'd3ea4f95-5d34-46e1-b940-91c4028caff5', null, { reportId: context.getArg('reportId') } ); context.setReturn('taskId', taskId);

uploadMedia

从可访问的 URL 下载资源并保存到 Zion 媒体存储:

context.uploadMedia( url: string, headers: Record<string, string> ): { mediaType: string; id: number }

不需要请求头时传入 {}。返回的 id 可以写入图片、视频或文件字段,也可以传给后续节点。

const media = context.uploadMedia( context.getArg('fileUrl'), {} ); context.setReturn('mediaId', media.id); context.setReturn('mediaType', media.mediaType);

用户与平台能力

SSO 用户信息

方法返回值说明
context.getSsoAccountId()number | null返回当前 SSO 用户对应的账号 ID;没有 SSO 身份时返回 null
context.getSsoUserInfo()string | null返回 SSO 提供方的用户信息 JSON 字符串;没有 SSO 身份时返回 null

需要读取用户信息字段时,先判断是否为空,再解析 JSON:

const rawUserInfo = context.getSsoUserInfo(); const userInfo = rawUserInfo ? JSON.parse(rawUserInfo) : null;

微信模板消息

Zion 的代码工具还提供 wechatSendTemplateMessageWithUserOpenId,用于向指定微信 OpenID 发送模板消息:

context.wechatSendTemplateMessageWithUserOpenId( token: string, wechatAppId: string, accountOpenId: string, templateId: string, pagepath: string, data: Record<string, any>, clientMsgId: string, url: string ): string

具体 Token、模板 ID、跳转地址和消息字段应来自当前微信服务号与小程序配置。可选字符串没有值时传入空字符串。

使用第三方库

运行环境不能直接执行 importrequire,但可以在本地将兼容的第三方库打包为自包含脚本,再把构建结果放在节点业务代码之前。

适合使用的库应同时满足以下条件:

  • 可以同步执行,不依赖 Promise 或异步初始化。
  • 不依赖 Node.js 内置模块、文件系统或原生扩展。
  • 不依赖 windowdocument、Worker 等浏览器能力。
  • 可以打包为单个 JavaScript 文件,且构建产物体积可控。

打包自包含脚本

以下示例使用 Webpack 将 crypto-js 输出为全局变量。先创建独立目录并安装依赖:

mkdir run-code-library cd run-code-library npm init --yes npm install --save-dev webpack webpack-cli npm install crypto-js

创建 entry.js

const CryptoJS = require('crypto-js'); module.exports = CryptoJS;

创建 webpack.config.js

const path = require('path'); module.exports = { mode: 'production', entry: './entry.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'crypto-js.bundle.js', library: { name: 'CryptoJS', type: 'var', }, }, };

运行构建:

npx webpack --config webpack.config.js

dist/crypto-js.bundle.js 的内容放在节点代码开头,再使用生成的全局变量:

// crypto-js.bundle.js 的内容 // ... const content = context.getArg('content'); const digest = CryptoJS.SHA256(content).toString(); context.setReturn('digest', digest);
⚠️

第三方库仍受节点沙箱和超时限制。固定并记录依赖版本,检查许可证和代码来源;升级依赖后重新构建并测试。不要使用来源不明的构建产物,也不要在库代码或日志中写入密钥。

测试与部署

  1. 使用节点测试覆盖正常输入、空值、边界值和失败场景。
  2. 通过 context.log()context.error() 和运行日志检查执行过程。
  3. 测试完整行为流,确认输出类型和下游绑定正确。
  4. 保存行为流后,通过 同步变更发布部署后端配置。

同步变更和发布都会更新行为流。部署后,所有调用该行为流的客户端都会使用新的代码逻辑。

⚠️

不要在日志中输出密码、Token、密钥、完整用户资料或其他敏感信息。

常见错误

错误检查方法
getArg 无法读取值确认输入已经在节点中声明、名称完全一致且绑定有值。
下游找不到返回值确认输出已经声明,且 setReturn 使用相同名称和兼容类型。
asyncPromise 或定时器报错将逻辑改为同步执行,使用会同步返回结果的 Context API。
windowfetchrequire 不存在运行环境不是浏览器或 Node.js;使用平台提供的 Context API。
GraphQL 字段不存在同步数据模型并刷新 GraphiQL,使用当前项目实际生成的字段和类型。
GraphQL Operation 执行失败检查 Operation 名称、Variables、{ role: 'admin' } 和运行日志。
API 返回空数据先检查 callThirdPartyApi 返回的 code,再按 API 配置读取 data
行为流调用失败确认同步行为流使用 callActionFlow,异步行为流使用 createActionFlowTask
节点超时检查循环、GraphQL、API 和同步行为流耗时,并确认项目版本对应的超时限制。
Last updated on