skip to Main Content

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:

TypeError: network error

Any idea how I can catch this error during processing of chunks from getReader?

2

Answers


  1. Chosen as BEST ANSWER

    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:

    const callApi = async () => {
      try {
        const response = await fetch('url', {});
        for await (const chunk of response.body) {
          console.log('next chunk to process:', chunk);
        }
      } catch (e) {
        console.log('Error:', e);
      }
    }
    

  2. 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’t await the reader.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).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search