FAQ: Router Parameters - router.param()

Community%20FAQs%20on%20Codecademy%20Exercises

This community-built FAQ covers the “router.param()” exercise from the lesson “Router Parameters”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Web Development

Learn Express

FAQs on the exercise router.param()

There are currently no frequently asked questions associated with this exercise – that’s where you come in! You can contribute to this section by offering your own questions, answers, or clarifications on this exercise. Ask or answer a question by clicking reply (reply) below.

If you’ve had an “aha” moment about the concepts, formatting, syntax, or anything else with this exercise, consider sharing those insights! Teaching others and answering their questions is one of the best ways to learn and stay sharp.

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head here.

Looking for motivation to keep learning? Join our wider discussions.

Learn more about how to use this guide.

Found a bug? Report it!

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

I don’t get how SpellBook.find(id, (err, spell) => {…}) works.
I understand that .find would usually have a callback function as an argument, and an optional thisArg. In this case it seems that we have a parameter, and then a callback. Where would err and spell come form? Is this something specific for app.param or a normal use of the .find method?

5 Likes

I have the same doubt. The same syntax is used here: https://expressjs.com/es/api.html

1 Like

Is the Number() function necessary for this logic to function?

app.param('spiceId', (req, res, next, id) => {
  const spiceId = Number(id);
  const spiceIndex = spiceRack.findIndex(spice => spice.id === spiceId);
  
  if (spiceIndex !== -1){
    req.spiceIndex = spiceIndex;
    next();
  } else {
    res.sendStatus(404);
  }
})
3 Likes

id is a string. But in the spiceRack array, the id key contains a value in number. So we need to convert id into number. Otherwise, the condition spice.id === spiceId will be false even if the ID is actually matched.

2 Likes

I also have exactly the same questions: why two arguments for the .find() array method and where err and spell come from.

I have asked for help in the Slack board. Hopefully someone will answer shortly…

@juandres1 @nungon @masakudamatsu

It’s pretty hard to tell what exactly is a SpellBook (what kind of object), but the .find method looks like a plausible method, so let’s jump into it.

In this snippet, we are retrieving a single record from the database and serving it back to the user, so this is a GET operation. Usually, we store our data in the external, separate entity - a database. So when we get a query to our API we usually have to:

  1. send some commands to the database;
  2. get output from the database;
  3. process the output and serve it back to the user.

The first step is pretty easy. We get the spellId from the query to our API and we simply execute made-up .find method that will send commands to the database to retrieve this record.


Digression. It’s hard to tell what kind of database and database driver is used in this example. But there is a MongoDB database and it has an amazing library for Node.js called mongoose. Mongoose models have method .findById which takes the same parameters as the method .find in the snippet -> https://mongoosejs.com/docs/api.html#model_Model.findById :slight_smile:


The second step is quite complicated. Because as we established earlier - the database is a separate entity. The same database might be used by multiple applications. Simply speaking - we have no idea when our database will respond. So for our application, it does not make sense to sit and wait, we have to process queries from other clients etc. That is why the callback function is sent as a second parameter to the .find method.

When the database sends back data, the callback function will be executed. Why the callback function has two parameters? Well, I said that we don’t know how fast database will respond to our query… in fact, we can’t be sure if the database still exists :smiley: So the first parameter err will be populated with any errors returned by the database or the client (if the database does not respond) and the second parameter spell will be storing the result from the database - found record.

The third step - process the output and serve it back to the user now is easy, we simply have to perform this operation in the callback function.


This whole concept of providing a callback that will be executed when some kind of operation finishes is called non-blocking access / non-blocking operation and is strictly related to the asynchronous nature of Node.js.

This is a nice guide explaining differences between blocking and non-blocking code -> https://nodejs.org/en/docs/guides/blocking-vs-non-blocking/.

2 Likes

Thanks for your detailed response. For someone slow, like myself, can this be summarised as saying that the .find() method given in the code example represents some custom method on whatever type of object a SpellBook is, rather than being the standard Array.prototype.find() method that I had assumed?

I think what is throwing me (us) off is that we’re assuming that SpellBook is simply an array, which is in line with all the other examples in this lesson.

1 Like

The lesson actually does state that it’s an Array:

We look up the spell in our SpellBook array using the .find() method.

2 Likes

Yes, exactly! :slight_smile:

Thank you for bringing this to my attention, I wasn’t aware of that. This is clearly wrong and misleading, I will report this as a bug.

Thanks for the response, and glad I’m not going crazy!

2 Likes

You’re very welcome :slight_smile:

1 Like

Thanks for such a helpful information

Going out on a limb here. I genuinely hope this helps many others after me. This section assumes the reader knows more than he/she may and doesn’t go to any length to make sure the reader is capable of performing the instructions. Forgive my critical tone. My desire is to help improve Codecademy as I have encouraged someone I love to follow down this path and I fear that person will also struggle. I have two degrees. I finished my most recent degree with a 4.0 (summa cum laude). So, I’m not a lazy student or one that would take the studies lightly. In this section the instructions read as though I would have known how to already write a function to search for “spiceIndex.” I spent hours trying to figure this out and none of my ideas for the solution were close enough for the testing software to conclude were correct. I’m not easily discouraged. But, Codecademy’s methods in this particular section leave me feeling highly insecure about my ability to code. I’m hoping someone from Codecademy uses this input to improve the section and expand on the steps to create the desired “functionality.” As I write this I’ll be highly embarrassed if I just missed it or shirked my “assumed” responsibilities as a student. But, as far as I can tell the lesson would be better if it expanded and used some level of repetition to ensure the student grasps the steps needed to write the desired functionality. Im exceeding grateful for the discussion in this area as it was helpful but ultimately I used the answers as a crutch. Again this left me feeling unprepared for the real world. This is in no way a complaint. I love Codecademy and am eternally grateful for mountains of knowledge for a rock bottom price. With any fortune my thought will reach the right folks to make this an even better environment for learning.

17 Likes

What can I actually put into the PATH field of the localhost site we have to get it to return a correct response body? So far I can only get it to show 404 or 0 status code and no response body

https://www.codecademy.com/courses/learn-express/lessons/middleware/exercises/middleware-review

I’m a little confused as the sudden call of
let spellId = Number(id);

I thought that the app.param returns the actual value of the parameter? So it passes it as a string?
Then what does Number() do? Why do we need it?
If it is to convert string to number then why can’t we use parseInt()?

I share the same thoughts. The lack of instruction left me a little insecure and uncertain how to proceed.

4 Likes

Why is SpellBook.find((spell) capitalized?

app.param('spellId', (req, res, next, id) => {
  let spellId = Number(id);
    try {
      const found = SpellBook.find((spell) => {
        return spellId === spell.id;
      })
      if (found) {
        req.spell = found;
        next();
      } else {
        next(new Error('Your magic spell was not found in any of our tomes'));
      };
    } catch (err) {
      next(err)
    }
});

https://www.codecademy.com/paths/back-end-engineer-career-path/tracks/becp-build-a-back-end-with-node-express-js/modules/fscp-learn-express-middleware/lessons/router-parameters/exercises/router-param

There’s a typo in the solution code for this exercise. Pimento is spelled wrong in the solution code.

1 Like

Is it right, that the app.param route (or how do you call it?) is only existent to create a req.param instance?

1 Like