Midway FaaS 提供了函数的本地开发、调用、测试整个链路,同时针对不同的平台触发器,也提供了完整的 TypeScript 参数定义。
开发函数
普通函数
普通的函数都是通过 “事件触发” - “函数调用” 的模型被执行,整个是一个过程式的执行逻辑。在 Midway FaaS 的封装后,我们将其变成了 class 写法,在便于 IoC 体系使用的同时,也满足代码复用。
class 的写法如下。
import { Func, Inject, Provide } from '@midwayjs/decorator'; // 装饰器包import { FaaSContext, FunctionHandler } from '@midwayjs/faas'; // midway faas 框架包@Provide() // 提供 IoC 容器扫描标识@Func('index.handler') // 标注函数入口export class IndexService implements FunctionHandler {async handler(event: any) { // <---- 函数体return 'hello world'; // 函数返回值}}
在上面我们的逻辑代码主要写在函数体中。
入口对应关系
Midway FaaS 通过 @Func 装饰器找到函数入口并执行, @Func 的入参为一个 handler 名字符串。这个字符串会和 f.yml 中的函数相匹配对应。
@Func('index.handler') // 函数的 handler
functions:index:handler: index.handlerindex2:handler: index.handler ## 这样配,两个不同的函数,会指向相同的代码
入口函数
@Func 装饰器既可以修饰 class,又可以修饰方法。
修饰到类
当修饰在 class 上时,默认会以 handler 方法作为函数入口。
@Provide()@Func('index.handler')export class IndexService implements FunctionHandler {async handler(event: any) {return 'hello world';}}
修饰到方法
**
而当 @Func 装饰器修饰到方法上时,更为自由,方法名可以完全自定义。
@Provide()export class IndexService {@Func('hi.handler')async sayHi(event: any) {return 'hello world';}@Func('hello.handler')async sayHello(event: any) {return 'hello world';}}
通过这样的方式,可以把多个函数放在同一个 class 上,中间的属性可以进行复用。
@Provide()export class IndexService {@Inject()ctx: FaaSContext; // 代码层面复用了这个 ctx 属性,但是实际调用时,上下文是分开的。@Func('hi.handler')async sayHi(event: any) {// TODO}@Func('hello.handler')async sayHello(event: any) {// TODO}}
函数参数
针对各个平台的函数入参,我们尽可能的做了 TypeScript 定义。
import { FaaSContext, FC, SCF } from '@midwayjs/faas';import { Func, Provide } from '@midwayjs/decorator';@Provide()export class TestTrigger {@Func('oss.handler')async aliyunOSS(event: FC.OSSEvent) {// TODO}@Func('cos.handler')async tecentCOS(event: SCF.COSEvent) {// TODO}}
具体的 Event 类型定义,请参考我们各个平台的触发器文档,比如 OSS 触发器。
HTTP 类型的触发器
包括阿里云的 http,以及其他平台的 API 网关类型,这些触发器最终是为了产生一个 HTTP 接口,我们希望在写 HTTP 接口中能够和传统应用尽可能接近,易于理解,对其入参进行了封装。
比如可以直接通过 ctx.query 获取 query 参数,通过 ctx.request.body 获取到 POST 的 body 参数,返回的时候可以直接挂载到 ctx.body 上。
import { FaaSContext, FC } from '@midwayjs/faas';import { Func, Inject, Provide } from '@midwayjs/decorator';@Provide()export class HTTPTrigger {@Inject()ctx: FaaSContext; // context@Func('every.handler')async getMethod() {const query = this.ctx.query;const body = this.ctx.request.body;this.ctx.body = 'hello world';}}
更多的 FaaSContext 函数上下文 API ,请查询 函数上下文文档。
本地调用
普通触发器函数
使用 f invoke 命令来调用普通函数,我们针对大多数平台的触发器都提供了模拟数据。
比如一个普通函数。
functions:index: # <----- 这个才是函数名handler: index.handlerevents:- timer:type: everyvalue: 1m
在执行以下命令后,会自动调用到函数的 handler。
$ f invoke -f [函数名]
HTTP、API 网关触发函数
针对 HTTP 和 API 网关类型的函数开发,我们做了一个高级支持,通过启动一个真实的 HTTP 服务器来模拟传统 Web 栈开发的样子。
比如一个 HTTP 函数:
functions:index:handler: index.handlerevents:- http:path: /*method: get
执行 f invoke -p ,默认会以 3000 端口启动服务。
如果函数代码如下:
import { Func, Provide } from '@midwayjs/decorator';@Provide()export class IndexService {@Func('index.handler')async handler() {return 'hello world';}}
则你能在浏览器中看到下面的输出。
:::info
第一次需要完整编译,会慢一些。
:::
整个启动服务的命令为。
$ f invoke -p$ f invoke -p 3000 // 默认端口 3000,可以修改$ f invoke -p 3000 --debug // 调试模式启动服务

