0

i am trying to build an app and i am very new to all this. So I've built a very simple function to get data from firestore and it works fine from a moment. This is the code:

 async getData(req, res) {
            const dataRef = db.collection(`${req.body.banco}`)
            let result = []
            dataRef.onSnapshot(docSnapshot => {
                docSnapshot.forEach(doc => {
                    const data = doc.data()
                    result.push(data)
                })
                console.log(result)
                return res.status(200).send(result)
            
            }, (error) => {
                console.log(`Erro encontrado: ${error}`)
            })
    }

My problem is that when I try to update any field from the document. It gets updated but I end up receiving this error:

node:_http_outgoing:576
    throw new ERR_HTTP_HEADERS_SENT('set');
    ^

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at new NodeError (node:internal/errors:372:5)
    at ServerResponse.setHeader (node:_http_outgoing:576:11)
    at ServerResponse.header (C:\Users\paulo\Desktop\sirius-back\functions\node_modules\express\lib\response.js:794:10)
    at ServerResponse.send (C:\Users\paulo\Desktop\sirius-back\functions\node_modules\express\lib\response.js:174:12)
    at ServerResponse.json (C:\Users\paulo\Desktop\sirius-back\functions\node_modules\express\lib\response.js:278:15)
    at ServerResponse.send (C:\Users\paulo\Desktop\sirius-back\functions\node_modules\express\lib\response.js:162:21)
    at C:\Users\paulo\Desktop\sirius-back\functions\src\controller\createDocs.js:70:40
    at QueryWatch.onNext (C:\Users\paulo\Desktop\sirius-back\functions\node_modules\@google-cloud\firestore\build\src\reference.js:1914:13)
    at QueryWatch.pushSnapshot (C:\Users\paulo\Desktop\sirius-back\functions\node_modules\@google-cloud\firestore\build\src\watch.js:469:18)
    at QueryWatch.onData (C:\Users\paulo\Desktop\sirius-back\functions\node_modules\@google-cloud\firestore\build\src\watch.js:353:26) {
  code: 'ERR_HTTP_HEADERS_SENT'
}

the app crashes and i have to start it over.

What is the reason of this? How can i get realtime updates from firestore databse after I update something from?

0

1 Answer 1

1

In Express you handle each requests by sending a single response to it. Since res a a response object, you can only send a response to the caller once. But since you're using onSnapshot, your code gets called for every change to the data too.

So initially, you load the data and send a response to the caller and all is 👍
But then when an update is made to the database, your code executes again and tries to send another response to the caller - and this is when you get an error.

The solution is to read the data only one with something like:

async getData(req, res) {
    const dataRef = db.collection(`${req.body.banco}`)
    let result = []
    dataRef.get().then((docSnapshot) => {
        docSnapshot.forEach((doc) => {
            const data = doc.data()
            result.push(data)
        })
        console.log(result)
        return res.status(200).send(result)
    }, (error) => {
        console.log(`Erro encontrado: ${error}`)
    })
}

Or a bit simplified:

async getData(req, res) {
    const dataRef = db.collection(`${req.body.banco}`)
    dataRef.get().then((docSnapshot) => {
        const result = docSnapshot.docs.map((doc) => doc.data());
        return res.status(200).send(result)
    }, (error) => {
        console.log(`Erro encontrado: ${error}`)
    })
}

Once you've called res.send(...) the request is complete and the client stops listening. Sending further updates to a response is not possible with an Express request/response model like you're using.

Also see:

You'll need to choose an infrastructure that allows a client to keep listening. Heads up: building something like that is quite involved, and you're likely better off if you use the client-side Firestore SDK to implement such realtime listeners

Sign up to request clarification or add additional context in comments.

2 Comments

it works but i would like to detect changes and update my aplicattion as soon as my update function finishes changing data from the database. And like this the data i had doesn't get reloaded. what would be the best the approach? i want to receive realtime changes to db
Sending further updates to a response is not possible with an Express request/response model like you're using. Once you've called res.send(...) the request is complete and the client stops listening. You'll need to choose an infrastructure that allows a client to keep listening. Heads up: building something like that is quite involved, and you're likely better off if you use the client-side Firestore SDK to implement such realtime listeners

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.