I'm building a chat app with AI API like ChatGPT. I'm streaming back the responses, which works fine in chrome and firefox, but does not in Safari. There I always get this error:
[Log] Error: (handleError.ts, line 8)
AxiosError
cause: TypeError: ReadableByteStreamController is not implemented
column: 28
config: {transitional: {silentJSONParsing: true, forcedJSONParsing: true, clarifyTimeoutError: false}, adapter: "fetch", transformRequest: Array, transformResponse: Array, timeout: 0, …}
line: 1697
message: "ReadableByteStreamController is not implemented"
name: "TypeError"
request: Request
body: ReadableStream {locked: true}
bodyUsed: true
cache: "default"
credentials: "same-origin"
destination: ""
headers: Headers {append: function, delete: function, get: function, has: function, set: function, …}
integrity: ""
keepalive: false
method: "POST"
mode: "cors"
redirect: "follow"
referrer: "about:client"
referrerPolicy: ""
signal: AbortSignal {aborted: false, reason: undefined, onabort: null, throwIfAborted: function, addEventListener: function, …}
url: "http://localhost:3000/conversations/cht_GHyzT4yB35_363xN"
Request Prototyp
sourceURL: "http://localhost:5173/node_modules/.vite/deps/axios.js?v=e4786436"
stack: "AxiosError@http://localhost:5173/node_modules/.vite/deps/axios.js?v=e4786436:375:2…"
AxiosError Prototyp
For my API Calls, I'm using a wrapper around Axios, which makes the streaming request like this:
async stream(data: any) {
try {
console.log("Sending request")
const response = await instance.post(this.baseUrl, data, { headers: {
'Accept': 'text/event-stream',
},
responseType: 'stream',
adapter: 'fetch'
});
// Handle response data
console.log("Request sent")
return { data: response.data, error: null };
} catch (error) {
// Handle errors
const handledError = await handleError(error);
return { data: null, error: handledError };
}
}
With this, the "Request Sent" does not get logged to the console, so the error has to be in the post request.
The request on safari finished quickly, probably with the first chunk of data coming in. in the api logs it says for requests with safari they only take a couple ms to finish.
I have found a workaround using the browser native fetch() library, that works fine. Issue seems to be with Axios.
EDIT: This is the working workaround
async *stream(data: any) {
try {
console.log('Sending request');
const response = await fetch(this.baseUrl, {
method: 'POST',
headers: {
Authorization: 'Bearer ' + token
Accept: 'text/event-stream',
'Content-Type': 'application/json',
},
body: JSON.stringify(data),
});
if (response.body) {
const reader = response.body.getReader();
const decoder = new TextDecoder('utf-8');
while (true) {
const { done, value } = await reader.read();
if (done) {
break;
}
const chunk = decoder.decode(value, { stream: true });
yield chunk;
}
}
console.log('Request sent');
} catch (error) {
const handledError = await handleError(error);
yield { error: handledError };
}
}
And then use this function to access the stream:
async function handleStream() {
const streamGenerator = await api
.from('conversations')
.byId(conversation.id)
.stream({
input
});
for await (const chunk of streamGenerator) {
if (chunk.error) {
// Handle error
console.error(chunk.error);
break;
}
// Process the chunk
console.log(chunk);
// Update your UI with the new chunk of data
}
}