最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JS流式模式輸出函數(shù)模式使用詳解

 更新時(shí)間:2026年04月03日 10:58:49   作者:任平安.  
文章介紹了傳統(tǒng)接口模式與AI項(xiàng)目需求不符的問(wèn)題,提出了流式模式和回調(diào)函數(shù)模式來(lái)解決,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

一、傳統(tǒng)模式:一次性返回完整結(jié)果

我們平時(shí)寫接口大多是這樣:

async function getAnswer(question: string): Promise<string> {
  const result = await callAI(question); // 等待完整結(jié)果(可能需要幾秒)
  return result; // 一次性返回
}
// 控制器中
const answer = await service.getAnswer(question);
ctx.body = { data: answer };

如果開發(fā) ai 相關(guān)的項(xiàng)目

問(wèn)題:用戶必須等待 AI 生成完整個(gè)回答才能看到內(nèi)容。如果 AI 生成需要 10 秒,用戶就白屏等待 10 秒,體驗(yàn)很差。

二、流式模式:邊生成邊返回

我們希望 AI 每生成一個(gè)字,就立刻推送給用戶。但 HTTP 響應(yīng)只能發(fā)送一次,不能先返回一部分再返回另一部分。解決辦法是:

  • 不關(guān)閉連接,保持 HTTP 響應(yīng)通道開啟,持續(xù)寫入數(shù)據(jù)塊(SSE 或分塊傳輸)。
  • 后端需要一種方式,能夠“每產(chǎn)生一個(gè) token 就調(diào)用一個(gè)函數(shù)”來(lái)寫入數(shù)據(jù)。

這就是 回調(diào)函數(shù)模式 的應(yīng)用場(chǎng)景。

三、回調(diào)函數(shù)模式模擬

想象你有一個(gè)函數(shù) generate,它模擬 AI 逐字產(chǎn)生結(jié)果:

// 模擬 AI 逐字生成
function simulateAI(word: string, callback: (token: string) => void) {
  for (const ch of word) {
    setTimeout(() => callback(ch), 100); // 每 100ms 輸出一個(gè)字符
  }
}

如果不用回調(diào),我們可能會(huì)寫:

function generateSync(word: string): string {
  let result = '';
  for (const ch of word) {
    result += ch;
    // 無(wú)法在這里把中間結(jié)果返回給調(diào)用方,因?yàn)楹瘮?shù)還沒(méi)結(jié)束
  }
  return result; // 只能最后一次性返回
}

使用回調(diào)后,調(diào)用方可以這樣:

simulateAI('你好', (token) => {
  console.log('收到 token:', token); // 會(huì)打印三次:你、好
});


回調(diào)函數(shù) (token) => { ... } 就像是“收到數(shù)據(jù)時(shí)的處理指令”。simulateAI 每產(chǎn)生一個(gè)字,就執(zhí)行這個(gè)指令,把字傳出去。

代碼中的實(shí)際應(yīng)用

BusinessChatService.chatStream 中:

async chatStream(input: string, onToken: (token: string) => void) {
  // ... 調(diào)用 LM Studio 流式 API
  for await (const chunk of stream) {
    // 解析出 token
    const token = parsed.choices[0]?.delta?.content;
    if (token) {
      onToken(token); // 每得到一個(gè) token,就調(diào)用外部傳入的回調(diào)
    }
  }
}

控制器調(diào)用時(shí):

await service.chatStream(input, (token) => {
  res.write(`data: ${JSON.stringify({ token })}\n\n`); // 將 token 寫入 HTTP 響應(yīng)
});

關(guān)鍵點(diǎn)

  • chatStream 不關(guān)心 token 最終被寫到哪里(可以是 HTTP 響應(yīng)、WebSocket、文件等),它只負(fù)責(zé)“產(chǎn)生 token 時(shí)調(diào)用回調(diào)”。
  • 控制器負(fù)責(zé)提供“寫入響應(yīng)”的具體實(shí)現(xiàn)(即回調(diào)函數(shù))。
  • 這樣實(shí)現(xiàn)了職責(zé)分離:服務(wù)專注于 AI 交互,控制器專注于網(wǎng)絡(luò)傳輸。
  • 在傳統(tǒng) CRUD 開發(fā)中,我們通常直接 return 數(shù)據(jù)庫(kù)查詢結(jié)果,很少需要“逐行返回”。
  • 流式輸出是 AI 應(yīng)用特有的需求,需要改變思維:從“等待完整結(jié)果”到“邊生成邊推送”。
  • 回調(diào)函數(shù)通常用于事件驅(qū)動(dòng)(如 addEventListener),但在這里用于異步迭代器的數(shù)據(jù)推送。

六、類比幫助你理解

想象你在廚房做菜(AI 生成回答),服務(wù)員(控制器)站在門口等。

  • 傳統(tǒng)模式:你把整盤菜做好后才端出去,顧客餓著肚子等很久。
  • 流式模式:你做一道菜(一個(gè)字)就讓服務(wù)員立刻端出去,顧客邊吃邊等。

服務(wù)員怎么知道菜做好了?你每完成一道菜就喊一聲“上菜!”(調(diào)用回調(diào)函數(shù))。服務(wù)員聽到后就把菜端走(寫入 HTTP 響應(yīng))。

在你的代碼中:

  • “你” = chatStream 方法
  • “上菜!” = onToken(token)
  • “服務(wù)員” = 控制器中傳入的箭頭函數(shù)

七、總結(jié)

  • 回調(diào)函數(shù)模式 在這里是為了實(shí)現(xiàn)流式輸出,避免用戶等待完整結(jié)果。
  • chatStream 不返回結(jié)果,而是通過(guò)反復(fù)調(diào)用 onToken 來(lái)“推送”數(shù)據(jù)塊。
  • 控制器負(fù)責(zé)提供“如何推送”的具體邏輯(寫入 HTTP 響應(yīng))。
  • 這種模式對(duì)于 AI 對(duì)話、實(shí)時(shí)數(shù)據(jù)處理非常實(shí)用。

到此這篇關(guān)于JS流式模式輸出函數(shù)模式使用詳解的文章就介紹到這了,更多相關(guān)js流式模式輸出內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

延边| 新源县| 沂水县| 全州县| 肥东县| 兴业县| 禄丰县| 奈曼旗| 嘉兴市| 松江区| 凌源市| 舒兰市| 海门市| 本溪市| 荃湾区| 富源县| 洪湖市| 如东县| 寻甸| 林芝县| 邛崃市| 全椒县| 侯马市| 紫阳县| 临武县| 馆陶县| 大姚县| 永济市| 云安县| 庄河市| 遂溪县| 晋中市| 永春县| 陆川县| 平凉市| 上蔡县| 泸水县| 台湾省| 张北县| 三明市| 商城县|