Node challenges - "done is not a function"

Receiving the error “done is not a function.” Yes, I did google and see similar forum posts. :slight_smile: I am fairly sure I am passing done correctly to my function (which was the issue in the posts), although that may not be the case. Forked repl.lit for editing here.

Relevant code:

var shortURLNumber = 0;

function createAndSaveURL(htmlInput, done) {

  shortURLNumber++;

  console.log("In create and save, shortURLNumber is "+shortURLNumber);

  const shortURLhere = ('/api/shorturl/' + shortURLNumber);

  var urlToSave = NewURL({long: htmlInput, short: shortURLhere});

  urlToSave.save (function(err, data) {
    if (err) {return console.error(err)};
    done(null, data);  //this is the line throwing an error according to the console
  });

};

and

app.post('/api/shorturl/new', urlParser, (req, res) => {
   //console.log("post url of " + req.body["url"]);
  
  createAndSaveURL(req.body["url"]); 

  res.json({
    url: req.body["url"]
   
  });
});

Thanks in advance, and for reference the challenge is here.

Shameless self-reply to bump this. Yes, createAndSaveURL needs two arguments and I was only passing one. But if I pass “done” or “done=Function” as the second, I still get errors, specifically the same error or “done is not defined.” Anybody?

Sorry we missed this post, the first time around. After 3 days, bumping is not a bad idea.

Remember how functions work:

function myFunc(argA, argB) {
  console.log(argA); // returns 2
  console.log(argB): // returns undefined
}
myFunc(2);

So, this would mean done === undefined

createAndSaveURL(req.body["url"]); 

Hope this helps

Thank you for the reply. And yes, the code above does not pass the second argument. But if I pass “done” or “done=Function” as a second argument, i.e.,

createAndSaveURL(req.body["url"], done); 

or

createAndSaveURL(req.body["url"], done=Function); 

I get errors as stated above. So I guess I am not passing done correctly but I am unclear as to how to do this properly?

i guess you can try this


function done(null, data){

}

 function createAndSaveURL(htmlInput,done) {

}

you are passing done as a callback thats probably why its throwing you an error. just correct me if im wrong.

Where do null and data come from? How were they defined?
Thanks

You need to define done…that is it. Add something like:

function done(err, docs) {
  if (err) ...
  if (docs.length) { console.log('success'); }
}

Do that. Or, do not use it even. Why do you want a done function?

  1. Regarding defining done, I was basically copying the structure from the Mongoose challenges. (Forked here.) As near as I can tell, done is never defined, but it just … works. Which is perplexing to me.

  2. As to why, my understanding was that it was good practice to have some sort of error-catching callback, although I would guess that having a done function is not the only way to go about that.

Right. That section can be confusing.

  1. freeCodeCamp has already defined done. So, you can find it in the boilerplate. I am AFK, so cannot find it right now. Just look for any argument passed to one of the imported functions from myApp.js. Probably in server.js but this is off the top of my head.

  2. Generally, it is good practice. By all means, keep it up. However, I have only ever come across one situation where I actually used such a style. Ideally, it is used for correct error handling. So, quite important in production apps, but for small-scale projects, mostly unnecessary.

Hope this clarifies.

1 Like

Ah that makes sense. I wrongly assumed it was some kind of integrated Node/Express function. But…

I ctrl-f’d every file in the repl and the github … and can’t find a done function.

So now I am more confused.

That is because the function is anonymously defined. Here is one of them:

var createPerson = require('./myApp.js').createAndSavePerson;
router.get('/create-and-save-person', function(req, res, next) {
  // in case of incorrect function use wait timeout then respond
  var t = setTimeout(() => { next({message: 'timeout'}) }, timeout);
  createPerson(function(err, data) {
    clearTimeout(t);
    if(err) { return (next(err)); }
    if(!data) {
      console.log('Missing `done()` argument');
      return next({message: 'Missing callback argument'});
    }
     Person.findById(data._id, function(err, pers) {
       if(err) { return (next(err)); }
       res.json(pers);
       pers.remove();
     });
  });
});

So, the function you have createAndSavePerson is imported from myApp.js:

  • It is renamed to createPerson (do not ask why)
  • The so-called done function is defined beginning: function(err, data) {
  • So, when you call done(null, doc), the err parameter is given a value of null, and the data parameter is given a value of doc.

I hope this clarifies.

2 Likes

Thank you, I noticed the function in there seemed to resolve the done function’s ability but I was/am still a little unclear on anonymously defined functions. (Will Google/read.) I assume the renaming of createPerson is so that there is a separate function for FCC to edit and it doesn’t clash with the camper’s createAndSavePerson funciont. But I will not ask why.

Anyway, thank you again for the multiple replies and clarifications, they are very helpful.

2 Likes