Alpit Anand
Alpit Anand

Reputation: 1248

Getting Error: Can't set headers after they are sent

I am trying to implement search functionality in Node, mongoose.
There is two parameter I like to search upon, either by name or artist. If any of the two matches with the current database it should return value(making it restful)

However, it is sending response Error: Can't set headers after they are sent.
and Unhandled promise rejections are deprecated and even the response which i am getting is empty

I am trying to execute two queries in it, which i think might be the problem. How should i write it, or what is a correct way to write these type of functionality

Here is my current code

app.get('/search/:textValue', controller.findData)

and the findData

exports.findData = (req, res)=>{

    const searchParam = req.params.textValue;
    let storeResult = []
    if(searchParam==null|| searchParam == undefined || searchParam==""){
        return res.status(500).json("Send a valid input")
     }
  else{
        Song.find({artists: new RegExp(searchParam, "i")}).lean().then((data)=>{
            storeResult[0].push(data)
        }).catch((err)=>{
            return res.send(err)
        })

        Song.find({name: new RegExp(searchParam, "i")}).lean().then((data)=>{
            storeResult[1].push(data)
        }).catch((err)=>{
            return res.send(err)
        })

        return res.send(storeResult)
    }
}

They are working for single queries perfectly fine, what changes should be made over here ?

Upvotes: 1

Views: 62

Answers (3)

molamk
molamk

Reputation: 4116

Problem

  1. You're starting with empty array let storeResult = []
  2. Then you access its first element (which does not exist) storeResult[0].push(data)
  3. This will trigger your catch callback. And then do a res.send(err)
  4. Even if you called return it will still continue in (req, res) => {} . This is because the return is only for the (err) => { // } callback
  5. Same thing with storeResult[1].push(data)
  6. Finally you call return res.send(storeResult) which effectively finishes your (req, res) => {} callback and return another response to the client

Solution:

When you push to your storeResult array, omit the index. Like this

storeResult.push(data)

Note

Even when pushing correctly, an error might happen while accessing the database. This is why you also need to chain your callbacks like O. Jones answer says

Upvotes: 1

O. Jones
O. Jones

Reputation: 108651

The way you have it you're using res.send(storeResult) before you fill in storeResult. How so? You fill it in with your .then() callbacks, which haven't yet been invoked.

Try chaining your then callbacks.

 Song.find({artists: new RegExp(searchParam, "i")}).lean()
.then((data)=>{
    storeResult.push(data);
})
.then(() => {
    Song.find({name: new RegExp(searchParam, "i")}).lean()
    .then((data)=>{

        storeResult.push(data)
    })
    .then(() => {
        console.log(storeResult)
        res.send(storeResult)
    })  
})
.catch((err)=>{
    console.log("Here is error")
    console.log(err)
    res.send(err)
})
}

Hint. Step-into in your debugger is useful for troubleshooting this kind of code.

Upvotes: 1

Dhaval
Dhaval

Reputation: 978

Try this:

exports.findData = (req, res)=>{
    let count=0;
    const searchParam = req.params.textValue;
    let storeResult = []
    if(searchParam==null|| searchParam == undefined || searchParam==""){
        return res.status(500).json("Send a valid input")
     }
  else{
        Song.find({artists: new RegExp(searchParam, "i")}).lean().then((data)=>{
            storeResult[0].push(data)
        }).catch((err)=>{
            count++;
            return res.send(err)
        })
        if(count == 0) {
            Song.find({name: new RegExp(searchParam, "i")}).lean().then((data)=>{
                storeResult[1].push(data)
            }).catch((err)=>{
                count++;
                return res.send(err)
            })
        }
        if(count == 0) {
            return res.send(storeResult)
        }
    }
}

Upvotes: 1

Related Questions