ChatGPT是如何實現不適用websocket進行一個一個字返回到前端的?
下面我們會介紹一下EventSource
EventSource
介面是 web 內容與伺服器傳送事件通訊的介面。
一個 EventSource
範例會對 HTTP 伺服器開啟一個持久化的連線,以 text/event-stream
格式傳送事件,此連線會一直保持開啟直到通過呼叫 EventSource.close()
關閉。
EventTarget <= EventSource
一旦連線開啟,來自伺服器端傳入的訊息會以事件的形式分發至你程式碼中。如果接收訊息中有一個 event 欄位,觸發的事件與 event 欄位的值相同。如果不存在 event 欄位,則將觸發通用的 message
事件。
與 WebSocket 不同的是,伺服器傳送事件是單向的。資料訊息只能從伺服器端到傳送到使用者端(如使用者的瀏覽器)。這使其成為不需要從使用者端往伺服器傳送訊息的情況下的最佳選擇。例如,對於處理如社交媒體狀態更新、訊息來源(news feed)或將資料傳遞到使用者端儲存機制(如 IndexedDB 或 web 儲存)之類的,EventSource
無疑是一個有效方案。
在Controllers
中新建一個StreamController.cs
檔案,並且提供一個IAsyncEnumerable<out T>
的Demo
IAsyncEnumerable<out T>
StreamController.cs
using Microsoft.AspNetCore.Mvc;
namespace WebApplication1.Controllers;
[ApiController]
[Route("[controller]")]
public class StreamController : ControllerBase
{
[HttpPost]
public async IAsyncEnumerable<char> Test()
{
const string value = "這是一個完整的測試資料;為了測試IAsyncEnumerable<T>的使用";
foreach (var v in value)
{
await Task.Delay(500);
yield return v;
}
await Task.CompletedTask;
}
}
上面案例的介面使用了IAsyncEnumerable<char>
,作為返回值,將value字串一個一個字元返回到前端。
每次返回等待500,這是伺服器端的實現,下面寫使用者端的實現,使用者端也是用.NET
首先啟動api服務,然後在開啟的swagger的瀏覽器介面中開啟開發者工具
使用F12
開啟開發者工具
在控制檯中新增fetchAsStream
方法用於呼叫IAsyncEnumerable<char>
的介面服務,程式碼如下
async function fetchAsStream(url,data) {
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(data),
});
if (!response.ok) {
const reader = response.body?.getReader();
const { done, value } = await reader.read();
throw new Error(
`Failed to fetch `
);
}
if (!response.body) {
throw new Error("ReadableStream not supported in this browser.");
}
const reader = response.body.getReader();
return {
[Symbol.asyncIterator]() {
return {
async next() {
const { done, value } = await reader.read();
if (done) {
return { done: true, value: null };
}
return {
done: false,
value: new TextDecoder("utf-8").decode(value),
};
},
};
},
};
}
輸入完成按確認鍵會顯示一個undefined
然後下一步就呼叫這個方法,當執行下面這個程式碼會發現控制檯會一個一個字顯示內容。
var stream = await fetchAsStream("http://localhost:5255/stream");
for await(var c of stream){
console.log(c);
}
看效果控制檯的字在一個一個輸出,請注意不要使用axios
,預設是不支援的。
來自token的分享
技術交流群:737776595