Skip to content

中间件

中间件是在消息处理程序之前调用的函数,它采用洋葱模型,即消息请求会依次通过所有中间件,而在消息响应时则会逆序通过中间件。中间件函数可以获取ApplicationContext对象,以便处理额外的业务逻辑。

消息处理程序

消息处理程序本质上也是一个中间件函数,不过它始终在所有中间件的最后面执行,是一个特殊的中间件。

中间件执行流程

中间件执行流程

全局中间件

当发起任何消息请求时,全局中间件都会在消息处理程序执行前执行。

应用域中间件

当发起应用域内的消息请求时,应用域中间件会在改应用域消息处理程序执行前执行。如果存在全局中间件全局中间件应用域中间件先执行。

中间件开发与使用

全局中间件

下面将以开发全局日志中间件功能为例,阐述如何开发和使用全局中间件。 在目录src/worker/common/middlewares下创建logger.ts,然后在logger.ts编写日志中间件代码逻辑,示例代码:

typescript
import { type ApplicationContext } from '@istock/iswork';

/**
 * 消息处理请求和响应日志
 * @param ctx
 * @param next
 */
export const logger = async (ctx: ApplicationContext, next: () => Promise<unknown>) => {
  const requestInfo = ctx.cmdp.getInfo();
  console.log('request:', requestInfo);
  await next();
  const responseInfo = ctx.cmdp.getInfo();
  console.log('responseInfo:', responseInfo);
};

接下来在src/worker/domain.ts中引入logger中间件及使用,代码示例:

typescript
// ...
import { logger } from '@/worker/common/middlewares/logger'; 
// ...
const bootstrap = async () => {
  // ...
  const app = new Application({
    emit: (message: unknown, options?: { targetOrigin?: string; transfer?: Transferable[] }) => {
      if (self.window) {
        console.debug(message, options ?? {});
      } else {
        self.postMessage(message, options ?? {});
      }
    },
  });
  app.useMiddleware(logger); 
  // ...
};
// ...

然后测试改功能是否正常。

应用域中间件

应用域中间件可以直接参考将股票名称转换成股票代码的中间件实现,代码路径为src/worker/common/middlewares/transform-stock-name.ts,代码示例:

typescript
import type { ApplicationContext, IDomainClass } from '@istock/iswork';
import type { TCmdRequest } from '@/worker/common';

interface IGlobalDomain extends IDomainClass {
  getStockCodeList: () => Promise<Array<{ name: string; code: string }>>;
}

/**
 * 将股票名称转换成股票代码
 * @param ctx
 * @param next
 */
export const transformStockName = async (ctx: ApplicationContext, next: () => Promise<unknown>) => {
  const { app, cmdp } = ctx;
  const data = cmdp.getPayload<TCmdRequest<{ 股票名称?: string; 股票代码?: string }>>();
  const domain = app.getDomain<IGlobalDomain>('global');
  if (domain?.domainClassInstance && data?.options?.['股票名称']) {
    const stockCodeList = await domain.domainClassInstance.getStockCodeList();
    if (stockCodeList.length) {
      const stockCode = stockCodeList.find((item) => item.name === data.options.股票名称);
      if (stockCode) {
        data.options.股票代码 = stockCode.code;
      }
    }
  }
  await next();
};

使用代码参考路径src/worker/domains/ag/ag.domain.ts,代码示例:

typescript
// ...
import { transformStockName } from '@/worker/common'; 
// ...

@Domain({
  name: 'ag',
  viewName: 'A股',
  // ...
  middlewares: [transformStockName], 
  // ...
})
export class AgDomain {}

免责声明:本站所有信息、数据、软件仅供学习研究,都不构成投资建议,本站不承担由此导致的任何责任。