上課學到的東東, 順手寫下筆記 依稀記得很多年前做爬蟲的時候無意間有做過類似的效果, 當時不曉得這個叫做 streaming
首先 api 的部分要回傳 IAsyncEnumerable<string>
然後用 await Task.Delay
來控制語速
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 [Route("api/[controller]")] [ApiController] public class LoremController : ControllerBase { private List<List<string>> textDict = new List<List<string>>() { new List<string>() { "好啊", "歡迎", "鳩咪", }, new List<string>() { "歸剛ㄟ", "社畜", "煩不煩", }, new List<string>() { "你好", "心靜自然涼", "長輩語錄", }, new List<string>() { "開心每一天", "與世無爭", "長輩語錄", }, }; [HttpGet("GetText")] public async IAsyncEnumerable<string> GetText(int speed = 2) { var rnd = new Random(); var current = rnd.Next(0, textDict.Count); foreach (var item in textDict[current]) { await Task.Delay(speed * 100); yield return item; } } }
前端 js 則是可以參考 mdn
1 2 3 4 5 6 7 8 9 10 11 12 async function readData (url ) { const response = await fetch(url); const reader = response.body.getReader(); while (true ) { const { done, value } = await reader.read(); if (done) { return ; } } }
他這個拿回來實際上會是一個 uint8array
還需要經過 TextDecoder
處理
1 2 3 4 const arr = new Uint8Array ([104 , 101 , 108 , 108 , 111 ]);const decoder = new TextDecoder();const str = decoder.decode(arr);
經過 decode 以後因為是 string array 的關係會變這樣
1 2 3 4 ["aaa", "bbb", "ccc", "ddd"]
我沒找到更好的方法來解, 發現 老外 也是用 regex 處理, 搭配 GPT 問起來就是這樣
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 async function getText (url ) { const response = await fetch(url); const reader = response.body.getReader(); async function * generateText ( ) { while (true ) { const { done, value } = await reader.read(); if (done) return ; yield value; } } for await (const chunk of generateText()) { const text = new TextDecoder().decode(chunk) .replace(/\[|]/g , '' ) .replace(/^,/ , '' ) .replace(/^"|"$/g , '' ); console .log(text) } }
想看完整效果的話可以到我的 codepen 然後把 url 改成你的網址並且開啟 CORS 即可 ~
See the Pen
SkypeGPT by 喇賽人 (@weber87na )
on CodePen .