I’m building a chatbot client using the Vue3 composition api. I have a fastapi backend post endpoint that returns a StreamingResponse. On the UI, I use a fetch request using the getReader method: https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/getReader
try {
fetch('api...', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: jsonPrompt
})
.then(response => {
if (!response.ok || !response.body) {
return;
}
const reader = response.body.getReader();
reader.read().then(function processText({ done, value }) {
if (done) {
console.log('Stream done');
return;
}
const decodedData = new TextDecoder('utf-8').decode(value);
console.log('decodedData:', decodedData);
//processStream(decodedData);
return reader.read().then(processText);
})
})
.catch(error => {
console.error('Error in promise:', error);
});
}
catch (error) {
console.error('Error:', error);
}
Occasionally, I get a TypeError: network error, after the stream has started, but before the done flag returns true, with the response status 200!? net::ERR_HTTP2_PROTOCOL_ERROR 200 (OK)
And the try catch
I added around the fetch does not catch this error:
Any idea how I can catch this error during processing of chunks from getReader?
2
Answers
The solution was rather easy: I used async await instead of a promise
then().catch()
as shown here Streams API and was able to catch the Network error.Here the simple change to the structure:
This can happen if the network goes down mid-stream, i.e. after headers have been sent (and therefore after
fetch
returned a fulfilled promise). Since you don’tawait
thereader.read()
, it will just return a rejected promise instead of throwing. See e.g. Asynchronous Programming.But if I were you, I would just use fetch-event-stream instead (or at least look at how it’s implemented).