Skip to content

创建声明式服务 ​

适用于具有稳定 HTTP 契约和具名操作的服务。本流程创建读取、创建两个方法,再检查它们真正产生的 HTTP 请求。

1. 准备编译器和服务端 ​

bash
pnpm add @ahoo-wang/fetcher@^5.0.0 @ahoo-wang/fetcher-decorator@^5.0.0
pnpm add -D typescript@6.0.3

使用 TypeScript 旧式装饰器编译;仅剥离类型的工具链不能执行参数装饰器。本包自身会导入 reflect-metadata,也不需要 emitDecoratorMetadata。将这些选项合并到应用 tsconfig:

json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "experimentalDecorators": true,
    "strict": true
  }
}

示例要求应用提供 GET /users/{id}?include=profile 和 POST /users,两者均返回 JSON { id, name }。请替换示例域名;这些是应用接口,不是 Fetcher 自带端点。

2. 定义并调用两个操作 ​

ts
import { Fetcher, ExchangeError } from '@ahoo-wang/fetcher';
import {
  api,
  body,
  get,
  path,
  post,
  query,
} from '@ahoo-wang/fetcher-decorator';

interface User {
  id: string;
  name: string;
}
const transport = new Fetcher({ baseURL: 'https://api.example.com' });

@api('/users', { fetcher: transport })
class UserService {
  @get('/{id}')
  getUser(
    @path('id') id: string,
    @query('include') include: string,
  ): Promise<User> {
    throw new Error('Replaced by @api');
  }

  @post('')
  createUser(@body() user: Omit<User, 'id'>): Promise<User> {
    throw new Error('Replaced by @api');
  }
}

export async function runUsers() {
  const users = new UserService();
  try {
    const ada = await users.getUser('42', 'profile');
    const lin = await users.createUser({ name: 'Lin' });
    return { ada, lin };
  } catch (error) {
    if (error instanceof ExchangeError) {
      console.error('HTTP status:', error.exchange.response?.status);
    }
    throw error;
  }
}

在应用中调用 runUsers(),并在 UI 或服务入口处理其拒绝的 Promise。第一个请求为 GET https://api.example.com/users/42?include=profile;第二个向 /users 发送 JSON {"name":"Lin"}。端点装饰器默认使用 JSON 提取器。

@api 会替换端点方法,原方法体和参数默认值初始化器都不会执行。因此写 include = 'profile' 不能补上查询参数。像上例一样显式传值,或另外定义普通包装方法。

3. 连接真实接口前验证 ​

在隔离测试中将 globalThis.fetch 替换为返回 Response.json({ id: '42', name: 'Ada' }) 的桩,调用 runUsers(),断言两个 URL、HTTP 方法和第二个请求体。用 finally 恢复原 fetch。这样可以一起验证装饰器和请求管线。

失败与生命周期 ​

出现提到 experimentalDecorators 的 TypeError 时,说明服务按标准装饰器编译,请启用该选项;绑定为 undefined 时检查参数顺序与参数装饰器。非 2xx 响应默认以 exchange 错误拒绝,JSON 解析也可能失败。返回类型 User 不会验证服务端 JSON。本例完整消费两个响应,没有需要销毁的监听器或流。

继续查阅服务与端点元数据、参数绑定及执行与取消。

apiDecorator.ts:154 实现了方法替换。

评估集成边界;返回本组任务。

基于 Apache License 2.0 发布。