0

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.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
Chanrithisak Phok
  • 1,590
  • 1
  • 19
  • 29
  • [This](https://stackoverflow.com/questions/7042340/error-cant-set-headers-after-they-are-sent-to-the-client#:~:text=The%20error%20%22Error%3A%20Can',body%20has%20already%20been%20written.) might be helpful – Naren Nov 05 '20 at 13:33
  • FYI: This is a API issue, No need to include Client Code – Naren Nov 05 '20 at 13:34
  • I have came across that, but the answer which everyone mentioned I don't understand, maybe I am fairly new to that concept and it would be more helpful if you pin point me to the exact solution. Thanks @Naren – Chanrithisak Phok Nov 05 '20 at 13:35
  • Can you more details of your code, route, middleware which handling this route – Naren Nov 05 '20 at 13:36
  • just this router.get('/products', auth, (req, res) => { initialPage.getBusinesses(res); }); – Chanrithisak Phok Nov 05 '20 at 13:36

1 Answers1

1

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();
    })
}
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807