Skip to content

Commit f19ac41

Browse files
committed
refactor(api/fetch): rework default/byob streaming
- improved XHR progress event handler - dequeue in load event - explicit support for 'text/event-stream' accept/content-type headers
1 parent 6cfdabf commit f19ac41

File tree

1 file changed

+26
-5
lines changed

1 file changed

+26
-5
lines changed

api/fetch/index.js

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ async function initBody (body, options, xhr) {
126126
if (this instanceof Request) {
127127
options.onxhr = (xhr) => {
128128
const accept = this.headers.get('accept') || ''
129-
if (accept.startsWith('text/')) {
129+
if (accept.startsWith('text/event-stream')) {
130130
try {
131131
xhr.responseType = 'text'
132132
} catch {}
@@ -135,7 +135,7 @@ async function initBody (body, options, xhr) {
135135
}
136136

137137
const contentType = this.headers.get('content-type') || ''
138-
if (xhr && contentType.startsWith('text/')) {
138+
if (xhr && contentType.startsWith('text/event-stream')) {
139139
let controller
140140
let byteOffset = 0
141141
this.body = new ReadableStream({
@@ -145,15 +145,36 @@ async function initBody (body, options, xhr) {
145145
}
146146
})
147147
xhr.addEventListener('load', () => {
148+
while (controller && byteOffset < xhr.responseText.length) {
149+
xhr.onprogress()
150+
}
151+
148152
if (controller) {
149153
controller.close()
154+
controller = null
150155
}
151156
}, { once: true })
152157
xhr.onprogress = () => {
153158
try {
154-
if (controller) {
155-
const buffer = textEncoder.encode(xhr.responseText.slice(byteOffset))
156-
byteOffset = xhr.responseText.length
159+
if (controller?.byobRequest) {
160+
const byteLength = controller.byobRequest.view.byteLength
161+
const bytesRead = Math.min(byteLength, xhr.responseText.length - byteOffset)
162+
const text = xhr.responseText.slice(byteOffset, byteOffset + bytesRead)
163+
const buffer = textEncoder.encode(text)
164+
165+
if (bytesRead === 0) {
166+
controller.close()
167+
controller = null
168+
} else {
169+
byteOffset += bytesRead
170+
controller.byobRequest.view.set(buffer)
171+
controller.byobRequest.respond(bytesRead)
172+
}
173+
} else if (controller) {
174+
const bytesRead = xhr.responseText.length - byteOffset
175+
const text = xhr.responseText.slice(byteOffset, byteOffset + bytesRead)
176+
const buffer = textEncoder.encode(text)
177+
byteOffset += bytesRead
157178
controller.enqueue(buffer)
158179
}
159180
} catch {}

0 commit comments

Comments
 (0)