Im trying to fetch a big amount of data from a db in JS using streaming to prevent loading all the data into memory at once. Im using express as my server and a nodeJS client that fetches the data using Axios. I’ve succesfully fetched the data with streaming but couldn’t figure out how to handle errors that happen while streaming.
Express Server:
app.get('/stream', async (req, res) => {
try {
const cursor = //fetch data with a limit & skip (MongoDB)
while(cursor.hasNext()) {
const data = await cursor.next()
const writeToStream = new Promise((resolve) => {
res.write(data, 'utf8', () => {
console.log("batch sent");
resolve()
})
})
await writeToStream
}
res.end()
} catch(error) {
console.log(`error: ${error.message}`)
//How do i send the status & error message to the requestor?
//return res.status(400).end(error.message) // <-- wanted behavior
})
Client:
try {
const res = await axios({
url: 'http://localhost:3000/test',
responseType: 'stream'
})
const { data } = res
data.pipe(someStream)
data.on('end', () => {
//stream finished
})
data.on('error', (error) => { // First Option
//error without a status or message
//res.status(error.status).send(error.message) // <-- wanted behavior
})
} catch(error) { // Second Option
//error without a status or message
//return res.status(error.status).send(error.message) // <-- wanted behavior
}
The error handeling on the client works (The code runs) but i couldn’t figure out how to send a status & message from the server to the client indicating an error and specifying it.
Versions:
"axios": "^1.5.1", "express": "^4.18.2"
Would appreciate some help.
Thanks ahead of time!
2
Answers
The thing is, you can not set headers after they are sent to the client. So when you start a stream using
res.write
the header is already sent as200
.What you can do is to use a trick. You can set a fixed prefix for both
DATA
andERROR
. In this way you can distinguish between what is real data and what is real error. I know its not the most efficient way, but works and seems plausible as the streaming stack does not provide the error management mechanism by itself at all.server.ts:
client.ts
Express Server:
In your server code, you want to make sure that if something goes wrong while sending data, you tell the client about it clearly. Here’s how:
Client Side:
On the client’s side, you’re doing well with the error part, but let’s break it down:
By making these changes, you’ll be able to handle problems while sending data, and you’ll tell the client about it in a simple and clear way.