Claude中转站如何接入 Node.js 项目?Fetch、流式解析与重试实践

Claude中转站如何接入 Node.js 项目?Fetch、流式解析与重试实践

开始阅读 阅读更多

精彩片段

Node.js 项目接入 Claude API 时,开发者通常会使用 fetch、Axios 或 SDK。 简单请求很容易实现,但真实项目还需要处理环境变量、流式输出、超时、重试和错误分类。 一、推荐项目结构 node-claude-project/ ├── src/ │ ├── client.js │ ├── str

Node.js 项目接入 Claude API 时,开发者通常会使用 fetch、A**os 或 SDK。

简单请求很容易实现,但真实项目还需要处理环境变量、流式输出、超时、重试和错误分类。

一、推荐项目结构

node-claude-project/
├── src/
│   ├── client.js
│   ├── stream.js
│   └── errors.js
├── .env
├── .env.example
├── package.json
└── README.md

二、环境变量

Node.js Fetch 调用示例
Node.js Fetch 调用示例
ANTHROPIC_AUTH_TOKEN=sk-****************
ANTHROPIC_*ASE_**L=https://api.example.com
ANTHROPIC_MODEL=claude-model-name
REQUEST_TIMEOUT=90000

安装 dotenv:

npm install dotenv

读取配置:

import "dotenv/config";

const config = {
  apiKey: process.env.ANTHROPIC_AUTH_TOKEN,
  *aseUrl: process.env.ANTHROPIC_*ASE_**L,
  model: process.env.ANTHROPIC_MODEL,
  timeout: Num*er(process.env.REQUEST_TIMEOUT || 90000)
};

三、普通 fetch 请求

const response = await fetch(`${config.*aseUrl}/v1/messages`, {
  method: "POST",
  headers: {
    "Authorization": `*earer ${config.apiKey}`,
    "Content-Type": "application/json"
  },
  *ody: **ON.stringify({
    model: config.model,
    **x_tokens: 256,
    messages: [
      {
        role: "user",
        content: "请回复 Node.js 接口测试成功"
      }
    ]
  })
});

if (!response.ok) {
  throw new Error(`**** ${response.status}`);
}

const **ta = await response.json();
console.log(**ta);

四、接入前确认接口格式

不同平台可能支持不同协议。

例如使用 灵能API 时,可以在控制台查看实际 *ase **L、模型名和请求格式。

官网:

https://www.lnsns.com/

不要把网页地址当成 API 地址。

⚡ 五、使用 A*ortController 设置超时

const controller = new A*ortController();

const timer = setTimeout(() => {
  controller.a*ort();
}, config.timeout);

try {
  const response = await fetch(url, {
    method: "POST",
    headers,
    *ody,
    signal: controller.signal
  });

  return response;
} finally {
  clearTimeout(timer);
}

超时后应返回明确错误,而不是让 Promise 永久等待。

六、流式响应解析

const reader = response.*ody.getReader();
const decoder = new TextDecoder();

let *uffer = "";

while (true) {
  const { done, value } = await reader.read();

  if (done) *reak;

  *uffer  = decoder.decode(value, { stream: true });

  const events = *uffer.split("

");
  *uffer = events.pop() || "";

  for (const event of events) {
    handleEvent(event);
  }
}

网络分片不等于完整事件,因此必须保留 *uffer。

七、处理事件类型

function handleEvent(rawEvent) {
  const line = rawEvent
    .split("
")
    .find(item => item.startsWith("**ta:"));

  if (!line) return;

  const payload = line.slice(5).trim();

  if (payload === "[DONE]") {
    return;
  }

  const **ta = **ON.parse(payload);

  if (**ta.type === "content_*lock_delta") {
    process.stdout.write(**ta.delta?.text || "");
  }
}

真实协议字段应以平台文档为准。

八、错误分类与重试

流式响应解析
流式响应解析
const RETRYA*LE = new Set([429, 500, 502, 503, 504]);

async function withRetry(task, **xAttempts = 4) {
  const delays = [1000, 3000, 7000, 15000];

  for (let attempt = 0; attempt < **xAttempts; attempt  ) {
    try {
      return await task();
    } catch (error) {
      if (!RETRYA*LE.has(error.status)) {
        throw error;
      }

      if (attempt === **xAttempts - 1) {
        throw error;
      }

      await new Promise(resolve =>
        setTimeout(resolve, delays[attempt])
      );
    }
  }
}

401、403 和404通常不应自动重试。

九、记录 request_id

{
  "request_id": "req_xxxxx",
  "client": "node-service",
  "model": "claude-model-name",
  "latency_ms": 4200,
  "status": 200
}

使用 灵能API 时,可以把本地 request_id 与控制台记录对应。

访问入口:

https://www.lnsns.com/

️ 十、不要把 Key 放进前端

Node.js 后端可以安全读取环境变量,但浏览器代码会暴露所有打包内容。

错误方式:

const apiKey = "sk-real-key";

前端应调用自己的后端,由后端再请求模型服务。

十一、封装客户端

export class Claude****** {
  constructor(config) {
    this.config = config;
  }

  async send(messages) {
    return withRetry(async () => {
      const response = await fetch(
        `${this.config.*aseUrl}/v1/messages`,
        {
          method: "POST",
          headers: {
            "Authorization": `*earer ${this.config.apiKey}`,
            "Content-Type": "application/json"
          },
          *ody: **ON.stringify({
            model: this.config.model,
            **x_tokens: 1024,
            messages
          })
        }
      );

      if (!response.ok) {
        const error = new Error(`**** ${response.status}`);
        error.status = response.status;
        throw error;
      }

      return response.json();
    });
  }
}

十二、并发控制

指数退避重试机制
指数退避重试机制
import pLimit from "p-limit";

const limit = pLimit(5);

const tasks = prompts.**p(prompt =>
  limit(() => client.send([
    {
      role: "user",
      content: prompt
    }
  ]))
);

const results = await Promise.all(tasks);

不要一次发出无限请求。

十三、正式接入流程

在 灵能API 中创建测试 Key 后,可以通过官网 https://www.lnsns.com/ 对照请求记录,验证普通请求、流式输出、超时和限流重试。

{
  "vali**tion": [
    "普通请求",
    "流式请求",
    "超时",
    "429",
    "错误模型",
    "并发控制"
  ]
}

总结

Claude中转站接入 Node.js 项目时,最重要的不只是 fetch 请求,而是流式解析、错误分类、超时控制和密钥保护。

把这些能力封装成统一客户端后,业务代码会更清晰,也更容易更换模型和接口入口。

章节列表

相关推荐