流程工具库
流程工具库提供了基础的流程管理控制功能。
运行流程
在Javascript语言中,运行一段流程代码可以有如下写法:
常规写法:
ts
// 流程中常涉及异步操作,因此定义为异步函数
async function flow () {
// 具体流程代码
}
// 执行流程
flow();极测推荐写法:
ts
// 执行流程
jc.invoke(async () => {
// 具体流程代码
jc.exit(); // 结束当前流程
});或
ts
// 执行流程
jc.main(async () => {
// 具体流程代码
});推荐采用jc.invoke()或jc.main()来定义并执行流程代码,可以显著提高代码的可读性。
jc.invoke()
调用一个传入的函数,并支持传入该函数的调用参数。例如在定义1个箭头函数的同时调用它,相比其它写法,使用本函数有助于让代码更有可读性。1个典型的应用场景是,在脚本代码的顶层内容中定义 & 执行1个异步(async)函数,以便在其中使用await来同步调用其它异步函数。
- 函数签名
ts
function invoke <Fn extends (...args: any[]) => any> (fn: Fn, ...args: Parameters<Fn>): ReturnType<Fn>;输入参数
- fn 待调用的函数
- args 调用时的输入参数
返回值:
fn的返回值代码示例
ts
jc.invoke(async () => {
await jc.sleepAsync(1000);
jc.exit();
})jc.main()
调用传入的函数,并在其运行结束后、用其返回结果来结束流程运行。本函数是个便利函数,内置了对jc.exit()等函数的调用操作,简化流程编写。实际上,本函数基本等价于如下代码实现:
ts
const main = async (fn: () => any) => jc.exit(await jc.invoke(fn));- 函数签名
ts
function main (fn: () => any): void输入参数
- fn 待调用的函数。类似于
C/C++或Java等编程语言中的main()函数,支持同步、异步的函数。其返回结果将作为流程结束状态并传给exit()函数。
- fn 待调用的函数。类似于
返回值:无
代码示例
ts
// 流程启动后,休眠1秒钟,然后结束
jc.main(() => jc.sleepAsync(1000))退出流程
由于极测采用了高度开放的脚本运行机制,允许脚本自主控制执行过程,并且难以实时监测脚本的运行状态。例如,脚本可能启动异步任务(如I/O操作或定时任务等)。当脚本运行返回时,不能据此推断脚本已完全终止运行。因此,脚本的执行终止只能通过调用 jc.exit() 来实现。
jc.exit()
结束当前流程,包含其所有子流程。但不会影响其父流程。
调用本函数之后,会触发当前流程的清理操作,包括结束其所有子流程、结束其开启的所有会话,以及特定模块自定义的清理函数,等等。
本函数返回之后,当前脚本不能 & 不应再执行其它操作,否则可能触发异常。
- 函数签名
ts
function exit (result?: string): void输入参数
- result 结束状态,可选。若省略或传入「空字符串」将被视为正常结束,否则视为异常/错误结束。该状态将作为结束信息记录到当前流程 及其 所有子流程。但只有根流程的信息会保存到数据库中。
返回值:无
代码示例
ts
jc.invoke(async () => {
// 休眠1秒钟
await jc.sleepAsync(1000);
// 正常结束
jc.exit();
})流程复用
通过调用jc.importWith()可以在当前流程代码中插入并执行其它页面的流程代码。
jc.importWith()
- 函数签名
ts
function importWith (pageName: string): void- 输入参数
- pageName 流程页面的名称,本函数将在当前空间中的所有「流程页面」中查找该名称对应的页面,
- 查找操作仅限流程页面,其余类型的页面都将被忽略,即使存在相同名称的页面,
- 若未找到指定名称的页面,或该页面的脚本为空,则子模块不会被实际执行,
- 若找到多个符合条件的页面,则始终使用按默认排序后的第1个页面,
- pageName 流程页面的名称,本函数将在当前空间中的所有「流程页面」中查找该名称对应的页面,
- 返回值:无
当函数返回后,指定流程(若存在)的执行结果将在当前流程的后续代码中使用。例如,可以调用导入流程中定义的函数等。
代码示例:
js
js.main(() => {
jc.importWith('模块示例1');
return jc.sleepAsync(1000);
})运行子流程
极测中的「流程」很大程度上可以类比为操作系统中的「进程」,因此「子流程」可以类比为「子进程」,即每个流程及其子流程具有隔离的、独立的资源空间,例如打开的协议接口等。当某个流程结束退出时(调用jc.exit()),会先结束其所有子流程,然后结束该流程自己。但若某个子流程结束时,不会影响其兄弟流程 & 父流程的运行。这与进程的结束方式类似。
jc.run()
创建子流程,执行传入的流程代码。
- 函数签名
ts
function run (script: string): void- 输入参数
- script 字符串,待运行的流程代码
- 返回值:无
代码示例
ts
jc.main(() => {
jc.run('jc.info("子流程已运行");')
return jc.sleepAsync(1000);
})jc.runWith()
创建子流程,执行指定页面的流程代码。
- 函数签名
ts
function runWith (pageName: string): void- 输入参数
- pageName 流程页面的名称,本函数将在「当前空间」中的所有「流程页面」中查找该名称对应的页面,
- 查找操作仅限流程页面,其余类型的页面都将被忽略,即使存在相同名称的页面,
- 若未找到指定名称的页面,或该页面的脚本为空,则子流程都不会被实际启动,
- 若找到多个符合条件的页面,则始终使用按默认排序后的第1个页面,
- pageName 流程页面的名称,本函数将在「当前空间」中的所有「流程页面」中查找该名称对应的页面,
- 返回值:无
代码示例:
js
js.main(() => {
jc.runWith('流程示例1');
return jc.sleepAsync(1000);
})流程动态
以日志分级的方式提供流程动态的记录接口。
jc.info()
- 函数签名
ts
function info (message: string): void- 输入参数
- message 字符串,「通知」级别的流程动态信息
- 返回值:无
代码示例
ts
jc.main(() => {
jc.info('流程已运行');
return jc.sleepAsync(1000);
})jc.warn()
- 函数签名
ts
function warn (message: string): void- 输入参数
- message 字符串,「告警」级别的流程动态信息
- 返回值:无
代码示例
ts
jc.main(() => {
jc.warn('流程异常');
return jc.sleepAsync(1000);
})jc.error()
- 函数签名
ts
function error (message: string): void- 输入参数
- message 字符串,「错误」级别的流程动态信息
- 返回值:无
代码示例
ts
jc.main(() => {
jc.error('流程错误');
return jc.sleepAsync(1000);
})数据编解码
在数据通信过程中,数据对象会经过编解码转换成 Buffer 对象。用户可以通过调用jc.decodeAs()将 Buffer 对象还原成数据对象;也可以通过调用jc.encodeFromAsync()将指定页面的某个数据对象转换成 Buffer 对象。
jc.decodeAs()
- 函数签名
ts
function decodeAs (payload: Buffer, segmentName: string): FlowDecodedSegment | undefined- 输入参数
- payload Buffer对象,数据完成编码后的字节流
- segmentName 字符串,数据段名称,数据段定义了解码的数据对象格式
- 返回值:
FlowDecodedSegment,解码后的数据对象类型,解码失败返回undefined
代码示例
ts
jc.main(() => {
const payload = Buffer.from([0xCA, 0xAA]);
const data = jc.decodeAs(payload, '示例数据段');
return jc.sleepAsync(1000);
})jc.encodeFromAsync()
- 函数签名
ts
function encodeFromAsync (pageName: string, contentName: string): Promise<Buffer | undefined>- 输入参数
- pageName 流程页面的名称,本函数将在「当前空间」中的所有「流程页面」中查找该名称对应的页面,
- 查找操作仅限流程页面,其余类型的页面都将被忽略,即使存在相同名称的页面,
- 若未找到指定名称的页面,或该页面的脚本为空,则子流程都不会被实际启动,
- 若找到多个符合条件的页面,则始终使用按默认排序后的第1个页面,
- contentName 字符串,数据名称,本函数将在指定页面中查询符合名称的数据对象
- pageName 流程页面的名称,本函数将在「当前空间」中的所有「流程页面」中查找该名称对应的页面,
- 返回值:编码后的Buffer对象,编码失败返回
undefined
代码示例
ts
jc.main(() => {
const payload = jc.encodeFromAsync('页面1', '数据1');
return jc.sleepAsync(1000);
})其他
jc.sleepAsync()
异步函数,休眠指定的时间。
- 函数签名
ts
type FlowTimeUnit = "ms" | "millis" | "millisecond" | "s" | "sec" | "second" | "m" | "min" | "minute" | "h" | "hour";
function sleepAsync (time: number, unit?: FlowTimeUnit): Promise<void>输入参数
- time 待休眠的时间值,其单位由
unit参数指定。 - unit 时间单位,可选,默认值为
"ms"。可选值包括:- 'ms' | 'millis' | 'millisecond',毫秒,
- 's' | 'sec' | 'second',秒,
- 'm' | 'min' | minute',分钟,
- 'h' | 'hour',小时,
- time 待休眠的时间值,其单位由
返回值:异步对象,待指定时间到达以后解析完成
代码示例
ts
// 流程启动后,休眠1秒钟,然后结束流程
jc.main(() => jc.sleepAsync(1000))