Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client NodeJS with Firebase

Description
Everytime I include response.send(snapshot.val()); this error is occurred and the NodeJS server crashed. I am using Postman to test the API endpoint with Header it is worked okay.

Output

On terminal 401 Unauthorized 

[2020-11-05T13:23:24.421Z]  @firebase/database: FIREBASE WARNING: Exception was thrown by user callback. Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

NodeJS

const getsRoute = require('./routes/gets');
app.use('/api/v1', getsRoute);

//on other file
const auth = require('../middleware/auth');
router.get('/products', auth, (req, res) => {
    initialPage.getBusinesses(res);
});

Code to Produce error

const initialPage = {
    getBusinesses(response) {
        ref.orderByKey()
        .limitToLast(20)
        .on('value', function(snapshot){
            response.json(snapshot.val()); 
            return snapshot.val();
        })
    }
}

Client side using React Native

  searchApi = async() => {
        const response = await axios.get('http://33c75838823c90.ngrok.io/api/v1/products',{
                headers: {
                    "Content-Type": "application/json",
                    "Accept": "application/json",
                    "x-auth-token":"jgiiHDgfdeizI1NiIJ9.eyJfaWQiOiI1ZmEwMWMzZmM4YjIwYjBjZDQyMmJkNzUiLCJpYXQiOjE2MDQ0MTAwMDZ0KwFAgVtsJUQw"
                }
            }
        ).catch((error) => {
            console.log("ERROR FROM AXIOS:", error)
          });
        console.log("RESPONSE DATA: %%%%%%%", response.data)
        this.setState({results: [response.data]});
       
    }

I have checked so many documents and questions forum but no one get exactly the solution suit for general problem.

Upvotes: 0

Views: 1110

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 599866

The problem is here:

getBusinesses(response) {
    ref.orderByKey()
    .limitToLast(20)
    .on('value', function(snapshot){
        response.json(snapshot.val()); 
        return snapshot.val();
    })
}

Since you're using on(...), your callback will be called:

  1. As soon as the data is loaded,
  2. After that, any time the data changes.

The first one is working as intended, but if the data ever changes this means you're trying to send another response, which is what's causing the error.

To solve this, use once instead of on:

getBusinesses(response) {
    ref.orderByKey()
    .limitToLast(20)
    .once('value', function(snapshot){
        response.json(snapshot.val()); 
        return snapshot.val();
    })
}

Upvotes: 1

Related Questions