精彩試讀
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二、环境变量

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 请求,而是流式解析、错误分类、超时控制和密钥保护。
把这些能力封装成统一客户端后,业务代码会更清晰,也更容易更换模型和接口入口。
正文目錄
相關書籍
友情鏈接