I am trying to fetch and console.log my data streamed from FastApi via the StreamedResponse using fetch but I cannot get it working. Chrome says Cannot read properties of null (reading 'getReader')
because response.body
is null. What am I doing wrong?
Server
async def foo():
for i in range(5):
time.sleep(1)
yield b'foobar'
@app.get('/bar')
async def bar():
return StreamingResponse(foo(), media_type='text/plain')
client
async function buttonclick() {
let url = 'http://localhost:8000/bar';
let options = {
mode: 'no-cors',
method: 'GET'
}
fetch(url, options)
.then(processChunkedResponse)
.then(onChunkedResponseComplete)
.catch(onChunkedResponseError);
}
function onChunkedResponseComplete(result) {
console.log('all done!', result)
}
function onChunkedResponseError(err) {
console.error(err)
}
function processChunkedResponse(response) {
var text = '';
var reader = response.body.getReader()
var decoder = new TextDecoder();
return readChunk();
function readChunk() {
return reader.read().then(appendChunks);
}
function appendChunks(result) {
var chunk = decoder.decode(result.value || new Uint8Array, {stream: !result.done});
console.log('got chunk of', chunk.length, 'bytes')
text += chunk;
console.log('text so far is', text.length, 'bytes\n');
if (result.done) {
console.log('returning')
return text;
} else {
console.log('recursing')
return readChunk();
}
}
}
A no-cors
Request.mode
returns an opaque response and "JavaScript may not access any properties of the resulting Response". Your server can provide header Access-Control-Allow-Origin
and the client should use a standard cors
fetch.
Additionally, you may need to make this change to ensure a Promise is returned:
if (result.done) {
//return text
return Promise.resolve(text)
}