Streaming Response'u UX'e Nasıl Yedirdim
Token akışı bir textarea değildir

Streaming'i açınca ilk his 'hızlı ürün' oldu. Metin aktı. Sonra bir araç cevabı JSON geldi; ilk parantez ekrana düştü, kullanıcı kopyaladı, yapıştırdı, kırıldı. Akış bir özellik değil, bir durum.
Durumlar sade: boş, akıyor, iptal, hata, bitti. Bunları tek bir string ile yönetmeye çalışmak, her tokenda tüm sayfayı yeniden düşünmek demek.
Yarım JSON'u göstermemek
Kullanıcıya akan şey düz metinse yazdırırım. Yapıysa biriktiririm, bitince parse ederim. Parse patlarsa ham metni 'bozuk çıktı' diye gösterir, yarım nesneyi vitrinlemiyorum.
type StreamState =
| { kind: "idle" }
| { kind: "text"; value: string }
| { kind: "done"; value: string }
| { kind: "error"; message: string };
export async function readTextStream(
res: Response,
onState: (s: StreamState) => void,
signal: AbortSignal,
): Promise {
if (!res.body) {
onState({ kind: "error", message: "govde yok" });
return;
}
const reader = res.body.getReader();
const dec = new TextDecoder();
let value = "";
onState({ kind: "text", value });
try {
while (!signal.aborted) {
const { done, value: chunk } = await reader.read();
if (done) break;
value += dec.decode(chunk, { stream: true });
onState({ kind: "text", value });
}
if (signal.aborted) {
onState({ kind: "error", message: "iptal" });
return;
}
onState({ kind: "done", value });
} catch (err) {
onState({ kind: "error", message: err instanceof Error ? err.message : "akis" });
} finally {
reader.releaseLock();
}
}
İptal, fetch signal. Signal yoksa sunucu üretmeye devam eder, sen ekranı durdurmuş olursun. Durmuş ekran, durmuş maliyet değildir — token yazısı yine fatura keser.
İmleç ve kaydırma
Her tokenda autoscroll, kullanıcının yukarı kaçışını ezer. Kullanıcı kaydırdıysa kilidi bırakıyorum; dibe inince yine bağlıyorum. İmleci metnin sonuna yapıştırmak, seçimi de bozar. Seçim varken akışı durdurmuyorum, seçimi ezmiyorum.
Bunu bir tasarım sistemi diye sunmuyorum. Üç durum ve bir abort. Yoksa streaming, titreyen bir textarea.
Yorumlar
Yorumlar (0)
Yorumlar üyelere açık. Üye ol · Giriş yap