• 简体中文
  • Request

    规划 API: 本页说明 request client 的最终用户用法。commflow@0.0.2 尚未导出 request runtime;不要将本页 import 当作当前生产导入。当前可运行导出见 当前版本快速开始

    适用场景

    request 适合一次性请求/响应通信:

    场景是否适合
    调用 REST API适合
    调用内部 HTTP 服务适合
    需要统一 timeout / retry / headers适合
    持续事件流使用 SSE
    双向实时消息使用 Socket
    过程式服务调用可考虑 RPC

    创建 client

    import { createCommflowRequestClient } from 'commflow';
    
    const request = createCommflowRequestClient({
      baseURL: 'https://api.example.com',
      timeout: 5000,
      retry: 2,
      headers: {
        accept: 'application/json'
      }
    });
    配置用户含义
    baseURL所有相对路径请求的默认服务地址。
    timeout单次请求最长等待时间。
    retry可重试失败的额外尝试次数,v1 使用数字。
    headers默认请求头。

    发送 GET 请求

    const response = await request.get('/users/42');
    
    if (!response.ok) {
      return null;
    }
    
    const user = await response.json();

    request 默认保留 fetch() 风格:HTTP 4xx/5xx 是响应,不是 transport error。用户应通过 response.ok、状态码或项目封装判断业务失败。

    发送 POST 请求

    const response = await request.post('/orders', {
      productId: 'p-100',
      quantity: 2
    });
    
    const order = await response.json();

    POST、PATCH 这类写操作默认不应随意重试。PUT、DELETE 虽然通常具备幂等语义,也应结合业务 idempotency key 和服务端保障再启用更积极的 retry。

    Body、query 与 Content-Type

    request helper 的默认规则:

    输入目标行为
    request.get('/users?active=1')query 留在 URL 字符串或 URLSearchParams,v1 不新增专属 query 字段。
    request.post('/orders', plainObject)plain object 默认序列化为 JSON,并在未显式设置时使用 content-type: application/json
    request.post('/upload', formData)FormDataBlobArrayBufferReadableStreamBodyInit 原样交给 fetch,不自动改 Content-Type。
    显式 headers['content-type']用户设置优先,commflow 不覆盖。

    使用 target 管理多个服务

    const request = createCommflowRequestClient({
      targets: [
        {
          name: 'user',
          baseURL: 'https://user.internal',
          timeout: 3000
        },
        {
          name: 'billing',
          baseURL: 'https://billing.internal',
          timeout: 8000,
          retry: 2
        }
      ]
    });
    
    const profile = await request.target('user').get('/profiles/42');
    const invoice = await request.target('billing').get('/invoices/latest');

    target 让用户按服务名组织请求,避免业务代码到处拼不同服务地址。

    单次调用覆盖配置

    await request.post('/orders', order, {
      timeout: 10000,
      retry: 0,
      headers: {
        'x-feature': 'checkout'
      }
    });

    覆盖顺序:

    来源优先级
    单次调用配置最高
    target 配置中等
    client 默认配置最低

    timeout 未设置时不添加 commflow 层超时;retry 未设置时为 0requestIdHeader 默认使用 x-request-id

    取消与 signal

    const controller = new AbortController();
    
    const responsePromise = request.get('/jobs/42', {
      timeout: 3000,
      signal: controller.signal
    });
    
    controller.abort();
    await responsePromise;

    当用户传入 signal 且同时设置 timeout 时,commflow 会把两者合并;任意一侧先触发都会取消请求,并抛出 kind: 'aborted'kind: 'timeout' 的结构化错误。

    注入请求上下文

    const request = createCommflowRequestClient({
      contextProvider() {
        return {
          requestId: 'req-123',
          propagatedHeaders: {
            'x-tenant-id': 'tenant-a'
          },
          metadata: {
            source: 'checkout'
          }
        };
      }
    });

    上下文适合放 requestId、tenant、trace metadata 等跨调用信息。业务参数不应塞进上下文,应作为请求 body、query 或 headers 明确传递。

    使用生命周期 hook

    const request = createCommflowRequestClient({
      hooks: {
        beforeRequest(event) {
          event.headers.set('x-request-source', 'commflow');
        },
        afterResponse(event) {
          console.log(event.request.method, event.response.status, event.durationMs);
        },
        onRetry(event) {
          console.warn('retrying request', event.attempt, event.reason);
        },
        onError(event) {
          console.error('request failed', event.error);
        }
      }
    });

    hook 用于日志、trace、headers 注入和诊断,不建议承载核心业务分支。详细边界见 配置指南

    错误处理

    try {
      const response = await request.get('/users/42');
    
      if (!response.ok) {
        return null;
      }
    
      return await response.json();
    } catch (error) {
      throw error;
    }

    错误模型见 错误与重试

    与 VextJS 的关系

    VextJS 接入优先从 request 能力切入:迁移时必须保留 app.fetch 的 timeout、retry、proxy、request context 和 hook 行为。详见 接入 VextJS