一文解析ChatGPT?之?Fetch?請求
SSE 介紹
隨著 ChatGPT 已生活工作中的一部分,介紹其中一種服務(wù)器端推送技術(shù)——Server-Sent Events (SSE),并簡單實現(xiàn)其效果。
SSE 是一種 HTML5 技術(shù),它允許服務(wù)器向客戶端發(fā)送事件,從而實現(xiàn)服務(wù)器端推送。相對于 WebSockets 或長輪詢技術(shù),SSE 提供了更簡單的方式來實現(xiàn)服務(wù)器端推送,并且支持更廣泛的客戶端和服務(wù)器端。
在 SSE 中,客戶端通過向服務(wù)器端發(fā)送一個 HTTP 請求,請求某個資源,并且指定響應(yīng)的類型是"text/event-stream"。服務(wù)器端在響應(yīng)請求時,將數(shù)據(jù)格式化為事件流的形式,并通過 HTTP 響應(yīng)發(fā)送回客戶端。客戶端通過事件流中的數(shù)據(jù),可以實現(xiàn)實時地更新 UI 等操作。
下面是一個 SSE 的 Demo,展示了如何通過 SSE 實現(xiàn)一個簡單的服務(wù)器端推送應(yīng)用。
服務(wù)端代碼:
const express = require('express'); const app = express(); const port = 3600; app.get('/stream', (req, res) => { const { message = '' } = req.query // 3個請求頭重點,需要返回text/event-stream,告知瀏覽器以何種類型解析 res.set({ 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', }); let step = 0; // 定時器依次返回message const time = setInterval(() => { const data = { message: message[step++]}; // 每個消息以 \n\n分割 res.write(`data: ${JSON.stringify(data)}\n\n`); if (step > message.length - 1) { res.end() clearInterval(time) } }, 500); }); app.listen(port, () => console.log(`Server running at http://localhost:${port}`));
客戶端代碼:
// 創(chuàng)建一個EventSource const eventSource = new EventSource(`/stream?message=${message}`); // 監(jiān)聽服務(wù)器返回的數(shù)據(jù) eventSource.onmessage = function (event) { console.log(event.data); }; eventSource.onerror = function () { eventSource.close(); };
在上面的代碼中,我們通過 EventSource
對象創(chuàng)建了一個 SSE 連接,并指定了服務(wù)器端的 URL。當有事件流數(shù)據(jù)時,onmessage
回調(diào)函數(shù)會被調(diào)用。 network 中可看到一條類型為eventsource
的請求,其以下內(nèi)容
咋和 ChatGPT 控制臺看到的內(nèi)容不一樣???
ChatGPT 回車后,并未發(fā)送eventsource
請求,而是發(fā)送了一個 fetch 請求,原因又是什么呢,仔細看
觀察上圖可得它發(fā)送了一個 fetch 的 POST 請求,服務(wù)端響應(yīng)的是一個eventsource
,那么 fetch 又能如何實現(xiàn)eventsource
響應(yīng)呢?因為 fetch 并沒有onmessage
方法~
通過一番查找學習~主要有兩個關(guān)鍵的 API
fetch用于發(fā)起SSE請求,而EventSource用于處理服務(wù)器端推送的數(shù)據(jù)。結(jié)合兩個API簡單實現(xiàn)一個fetchStream
方法
const fetchStream = (url, params) => { const { onmessage, onclose, ...otherParams } = params; const push = async (controller, reader) => { const { value, done } = await reader.read(); if (done) { controller.close(); onclose?.(); } else { onmessage?.(Uint8ArrayToString(value)); controller.enqueue(value); push(controller, reader); } }; // 發(fā)送請求 return fetch(url, otherParams) .then((response) => { // 以ReadableStream解析數(shù)據(jù) const reader = response.body.getReader(); const stream = new ReadableStream({ start(controller) { push(controller, reader); }, }); return stream; }) .then((stream) => new Response(stream, { headers: { 'Content-Type': 'text/html' } }).text()); };
調(diào)用方法
fetchStream(`/stream?message=${message}`, { method: 'GET', headers: { 'accept': 'text/event-stream', 'Content-Type': 'application/json', }, onmessage: (res) => { // todo console.log(res); }, });
經(jīng)過簡單封裝實現(xiàn)ChatGPT的應(yīng)答請求效果~
另外推薦一個成熟的第三方依賴fetch-event-source
點擊查看
Server-Sent Events 相對于其他技術(shù)的優(yōu)缺點
與WebSockets相比,SSE技術(shù)的優(yōu)點在于:
- 更簡單的實現(xiàn):SSE技術(shù)使用標準的HTTP協(xié)議來發(fā)送和接收數(shù)據(jù),因此不需要額外的握手和協(xié)議協(xié)商步驟。這使得SSE技術(shù)的實現(xiàn)更加簡單,尤其是對于服務(wù)器端。
- 更廣泛的兼容性:SSE技術(shù)使用標準的HTTP協(xié)議,因此可以被大多數(shù)Web瀏覽器和服務(wù)器端支持。相比之下,WebSockets需要瀏覽器和服務(wù)器端都支持WebSocket協(xié)議。
- 更少的網(wǎng)絡(luò)開銷:SSE技術(shù)使用HTTP長連接來實現(xiàn)服務(wù)器端推送,因此相比WebSockets需要更少的網(wǎng)絡(luò)開銷和資源消耗。
與長輪詢技術(shù)相比,SSE技術(shù)的優(yōu)點在于:
- 實時性更好:SSE技術(shù)可以實時地向客戶端推送數(shù)據(jù),因此可以實現(xiàn)更快的響應(yīng)速度和更好的實時性。
- 更少的網(wǎng)絡(luò)開銷:SSE技術(shù)使用HTTP長連接來實現(xiàn)服務(wù)器端推送,因此相比長輪詢需要更少的網(wǎng)絡(luò)開銷和資源消耗。
- 更好的客戶端兼容性:SSE技術(shù)可以被大多數(shù)現(xiàn)代瀏覽器和設(shè)備支持,因此更容易實現(xiàn)客戶端兼容性。
總結(jié)
最后呈上一個完整的demo,github地址
以上就是一文解析ChatGPT 之 Fetch 請求的詳細內(nèi)容,更多關(guān)于ChatGPT Fetch 請求的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
一個超簡單的JS拖拽實現(xiàn)代碼(兼容IE,Firefox)
網(wǎng)上找的一個超簡單的JS拖拽,喜歡拖拽效果的朋友可以參考下。2010-04-04Vuejs通過拖動改變元素寬度實現(xiàn)自適應(yīng)
這篇文章主要介紹了Vuejs通過拖動改變元素寬度實現(xiàn)自適應(yīng),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-09-09JavaScript函數(shù)聲明和函數(shù)表達式的區(qū)別
這篇文章主要介紹了JavaScript函數(shù)聲明和函數(shù)表達式的區(qū)別,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-06-06微信小程序表單驗證插件WxValidate的二次封裝功能(終極版)
這篇文章主要介紹了微信小程序表單驗證插件WxValidate的二次封裝功能(終極版),文中給大家提到了最終版與前面2版的不同點,需要的朋友可以參考下2019-09-09基于JavaScript實現(xiàn)移除(刪除)數(shù)組中指定元素
在Array對象中有給定的函數(shù)可以刪除數(shù)組中指定的元素,雖然非常好用,但是總感覺看不到摸不著的比較別扭,下面就分享一個自定義的刪除數(shù)組指定索引值元素的函數(shù),希望給大家一個全新的思路2016-01-01javascript完整操作Table的增加行,刪除行的列子大全
非常漂亮的js操作table行代碼函數(shù)。比較方便2008-10-10