0

I am practicing building a simple Express app with MongoDB. I created an endpoint that will search for a user by name and then render the page with the stored data from the DB. I tried to integrate some code to handle when a profile is not found, but it breaks the app.

This code works- the profile page renders as expected:

app.get('/profiles/:name', (req, res) => {
    // calling the model
    Profile
        .find({ "name.first": req.params.name })
        .then(profileArray => {
            let profile = profileArray[0];
            let img =
                `<img class="ui rounded image" src="http://api.adorable.io/avatar/250/${profile.name.first}${profile.age}" />`
            res.render('profile', { profile, img });
        })
        .catch(error => {

            if (error.reason === "ValidationError") {
                console.log(error);
                let response404 = error;
                res.render('add', { response404 });
            }
            else {
                console.log(error);
                res.render('add');
            }

        });
});

But when I integrate the following code- between find() and then() - it breaks the app:

    .count()
    .then(count => {
        if (count < 1) {
            return Promise.reject({
                code: 404,
                reason: "ValidationError",
                message: "Profile not found. Please create a profile."
            })
        };
    })

Here is the full endpoint code with the snippet that causes the crash:

app.get('/profiles/:name', (req, res) => {
    // calling the model
    Profile
        .find({ "name.first": req.params.name })
        .count()
        .then(count => {
            if (count < 1) {
                return Promise.reject({
                    code: 404,
                    reason: "ValidationError",
                    message: "Profile not found. Please create a profile."
                })
            };
        })
        .then(profileArray => {
            let profile = profileArray[0];
            let img =
                `<img class="ui rounded image" src="http://api.adorable.io/avatar/250/${profile.name.first}${profile.age}" />`
            res.render('profile', { profile, img });
        })
        .catch(error => {

            if (error.reason === "ValidationError") {
                console.log(error);
                let response404 = error;
                res.render('add', { response404 });
            }
            else {
                console.log(error);
                res.render('add');
            }

        });
});

It throws this error: "TypeError: Cannot read property '0' of undefined". It is referring to the second then() where I am trying to access the array returned from find().

It seems like the data from find() is getting lost. How can I pass the found document through count() and the first then()?

One thing to note. When I integrate the error handling code, I reject the promise and render a new page with a form. That part works, but when trying to render the page with a name that does exist in the DB it breaks. I'm losing the data somewhere along the chain. Let me know if you need anything clarified. Thanks.

bprdev
  • 693
  • 9
  • 12
  • Try to check if the count variable getting the proper value from promise – zb22 Jan 27 '18 at 08:01
  • yeah it gets the expected value. I console logged count just before the condition and inside it. It never enters the if condition when a profile is found, which is expected. So if a profile is found, then how do I continue? It seems to stop there instead of continue to the next promise in the chain. – bprdev Jan 27 '18 at 08:11
  • 1
    When you doing 'find' and then 'count', you losing the result of 'find', see this: https://stackoverflow.com/questions/35443821/find-and-count-elements-of-collection-with-mongoose – zb22 Jan 27 '18 at 08:28
  • @zb22 good find. I gave you an upvote. However, already accepted an answer. Thanks for the help. – bprdev Jan 27 '18 at 08:34

1 Answers1

3

there is another way to do this.

Profile.find({ "name.first": req.params.name })
.then((docs) => {
  if(docs.length < 1) {
    return Promise.reject({
         code: 404,
         reason: "ValidationError",
         message: "Profile not found. Please create a profile."
   })
   let profile = docs[0];
   let img =`<img class="ui rounded image" src="http://api.adorable.io/avatar/250/${profile.name.first}${profile.age}" />`
        res.render('profile', { profile, img });
  })
   .catch(error => {
        if (error.reason === "ValidationError") {
            console.log(error);
            let response404 = error;
            res.render('add', { response404 });
        }
        else {
            console.log(error);
            res.render('add');
        }
    });
});

you can get the count of docs by using docs.length and the docs contain the data returned by mongoDB. This is an alternate approach.

bprdev
  • 693
  • 9
  • 12
Faraz Sarwar
  • 238
  • 1
  • 9
  • oh yeah because find() returns an array. I should have thought of that! But that is why I love this site. Thanks for the help. I am happy with this alternate approach. – bprdev Jan 27 '18 at 08:32
  • I made an edit, in case this thread is helpful to someone in the future. – bprdev Jan 27 '18 at 08:44