必须通过自建node.js代理中转调用豆包api实现流式响应,因浏览器cors限制;代理需设transfer-encoding: chunked、content-type: text/event-stream,并用axios responsetype: 'stream'透传sse;前端用fetch+readablestream解析,逐块解码utf-8、按data:分割、提取choices[0].delta.content累加textcontent。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜

要在前端 JavaScript 中调用火山引擎豆包 API 并实现消息的流式返回(即逐字、逐 token 渲染响应),必须绕过浏览器同源限制和 CORS 策略,不能直接 fetch 豆包的 /v1/chat/completions 接口;你需要通过自建代理中转,且后端需显式设置 Transfer-Encoding: chunked 与正确的 Content-Type。
准备豆包 API 密钥与模型配置
登录火山引擎控制台 → 进入「机器学习平台 VeDI」→ 找到「豆包大模型」服务 → 创建 API Key;复制 AppID、API Key、Secret Key,三者缺一不可。其中 Secret Key 【仅首次生成时可见,关闭页面后无法再次查看】。
确认你要调用的模型 ID,例如:doubao-pro-32k 或 doubao-lite-4k;不同模型对 stream 参数支持程度不同,doubao-pro-32k 支持 true,doubao-lite-4k 不支持流式,强行传 stream=true 会报错 400。
搭建 Node.js 代理服务(必需)
新建一个 Express 服务,安装依赖:npm init -y && npm install express axios cors crypto
创建 server.js,写入以下逻辑:监听 /api/chat,接收前端 POST 请求 → 用 crypto 拼接签名字符串(含 timestamp、nonce、body)→ 用 axios 发起带 Authorization 头的 POST 到 https://ark.cn-beijing.volces.com/api/v3/chat/completions → 设置 { responseType: 'stream' } → 将响应流 pipe 给 res,同时设置 res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' })。
注意:axios 默认不透传流式响应,必须显式设置 { responseType: 'stream' },否则会等待整个 body 下载完才触发 then,彻底失去流式意义。
前端发起流式请求并解析 SSE
使用 EventSource 或 fetch + ReadableStream;推荐 fetch,兼容性更好且可中断。
方法一:用 fetch + response.body.getReader()
const controller = new AbortController();
const response = await fetch('/api/chat', { method: 'POST', body: JSON.stringify({ messages: [{ role: 'user', content: '你好' }], model: 'doubao-pro-32k', stream: true }), headers: { 'Content-Type': 'application/json' }, signal: controller.signal });
const reader = response.body.getReader();
while (true) { const { done, value } = await reader.read(); if (done) break; const chunk = new TextDecoder().decode(value); console.log(chunk); }
方法二:用 EventSource(需后端返回格式严格匹配 text/event-stream)
const es = new EventSource('/api/chat');
es.onmessage = e => { const data = JSON.parse(e.data); if (data?.choices?.[0]?.delta?.content) { document.getElementById('output').textContent += data.choices[0].delta.content; } };
es.onerror = () => es.close();
⚠️ 关键点:EventSource 自动忽略以 : 开头的注释行,但豆包返回的 chunk 是标准 JSON 对象,不是 event: message + data: {...} 格式;所以方法二要求你在 Node.js 代理里手动包装成 SSE 格式——每收到一个豆包 chunk,就 write `data: ${JSON.stringify(chunk)}\n\n`。
解析豆包流式 chunk 并拼接完整回复
第一步:监听流数据到达,用 Uint8Array 接收原始字节流;
第二步:用 TextDecoder 逐块解码,注意不要在中间断开 UTF-8 字符(如 emoji 或中文),TextDecoder({ fatal: false, ignoreBOM: true }) 可自动处理;
第三步:将解码后的字符串按 \n\n 分割,过滤空行;每段内容以 data: 开头,提取其后 JSON 部分;
第四步:JSON.parse 后检查 choices[0].delta.content 字段是否存在——这是实际返回的文本片段;若为 null 或 undefined,说明是结束帧或系统信息,跳过;
第五步:将所有非空 content 字符串累积追加到 DOM 元素中,用 innerHTML += 会触发重排,改用 textContent += 更安全;【不要用 innerHTML +=,存在 XSS 风险,豆包输出未做 HTML 转义】。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!







