You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Cloudflare Worker将OpenAI响应流式返回至前端?

解决Cloudflare Worker流式转发OpenAI响应的问题

问题分析

你的代码当前会等待OpenAI的完整响应返回后才向前端输出数据,核心原因是:

  • 在返回Response之前就完成了整个for await...of循环,把所有数据写入TransformStream,导致前端必须等所有数据处理完才能收到响应
  • 未利用Cloudflare Worker的ctx.waitUntil方法,无法确保Worker在返回响应后仍能后台处理流数据

修复后的Worker代码

export default {
    async fetch(request, env, ctx) {
        const openai = new OpenAI({
            apiKey: "##-#######"
        });

        // 请求OpenAI API获取流式响应(无需await整个结果,直接拿到AsyncIterable)
        const stream = openai.chat.completions.create({
            model: "gpt-3.5-turbo",
            messages: [{ role: "user", content: "Tell me a story using 2000 chars." }],
            stream: true
        }, { responseType: "stream" });

        // 创建TransformStream处理流式数据
        const transformStream = new TransformStream({
            async transform(chunk, controller) {
                // 提取OpenAI返回的内容片段
                const content = chunk.choices[0]?.delta?.content || "";
                if (content) {
                    // 将内容编码后发送到前端
                    controller.enqueue(new TextEncoder().encode(content));
                }
            }
        });

        // 用waitUntil确保Worker返回响应后继续后台处理流转发
        ctx.waitUntil(
            (async () => {
                for await (const part of stream) {
                    await transformStream.writable.getWriter().write(part);
                }
                await transformStream.writable.getWriter().close();
            })()
        );

        // 立即返回流式响应,前端可开始接收分块数据
        return new Response(transformStream.readable, {
            headers: {
                'Content-Type': 'text/plain; charset=utf-8',
                'Access-Control-Allow-Origin': '*',
                'Access-Control-Allow-Headers': 'Origin, X-Requested-With, Content-Type, Accept',
                'Transfer-Encoding': 'chunked',
                'Cache-Control': 'no-cache' // 禁用缓存,保证流式传输生效
            }
        });
    }
};

关键改动说明

  • 提前返回Response:不再等待所有流数据处理完毕,立即返回包含transformStream.readable的Response,让前端能马上开始接收分块数据
  • 使用ctx.waitUntil:告知Cloudflare Worker在返回响应后继续后台处理流的转发,避免Worker提前终止导致流中断
  • 规范处理流数据:用TransformStream的transform方法处理每个chunk,避免手动管理writer的背压问题
  • 添加Cache-Control头:防止中间缓存(如Cloudflare CDN)将流式响应缓存为完整内容,确保分块传输生效

前端代码优化(可选)

前端代码基础逻辑没问题,可优化解码逻辑避免字符乱码:

const onSubmit = async (data) => {
    try {
        const response = await fetch('CLOUDFLARE_END_POINT');

        if (!response.body) {
            console.error('浏览器不支持流式响应或服务器未返回流');
            return;
        }

        const reader = response.body.getReader();
        const decoder = new TextDecoder('utf-8');
        let receivedText = '';

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

            if (done) {
                console.log('流传输完成');
                break;
            }

            // 解码当前chunk并拼接,避免跨chunk的字符乱码
            receivedText += decoder.decode(value, { stream: true });
            console.log(receivedText);
            // 这里可将receivedText渲染到页面
        }
    } catch (error) {
        console.error('请求数据出错:', error);
    }
};

前端优化点

  • 复用同一个TextDecoder实例,使用{ stream: true }选项确保跨chunk的多字节字符正确解码
  • 拼接已接收文本,方便直接渲染到页面

内容的提问来源于stack exchange,提问作者allegutta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 03:24:55