Help with mongoose done() function please

What’s happening:

I’m trying to do the “Create and Save a Record of a Model” challenge in the MongoDB and Mongoose challenges (APIs and Microservices section) and I have an error saying:

throw er; // Unhandled 'error' event
      ^

TypeError: Cannot read property 'remove' of null
    at /home/runner/boilerplate-mongomongoose/server.js:104:12
    at /home/runner/boilerplate-mongomongoose/node_modules/mongoose/lib/model.js:4866:16
    at /home/runner/boilerplate-mongomongoose/node_modules/mongoose/lib/model.js:4866:16
    at /home/runner/boilerplate-mongomongoose/node_modules/mongoose/lib/helpers/promiseOrCallback.js:24:16
    at /home/runner/boilerplate-mongomongoose/node_modules/mongoose/lib/model.js:4889:21
    at /home/runner/boilerplate-mongomongoose/node_modules/mongoose/lib/query.js:4399:11
    at /home/runner/boilerplate-mongomongoose/node_modules/kareem/index.js:136:16
    at processTicksAndRejections (internal/process/task_queues.js:79:11)
Emitted 'error' event on Function instance at:
    at /home/runner/boilerplate-mongomongoose/node_modules/mongoose/lib/model.js:4868:13
    at /home/runner/boilerplate-mongomongoose/node_modules/mongoose/lib/helpers/promiseOrCallback.js:24:16
    [... lines matching original stack trace ...]
    at processTicksAndRejections (internal/process/task_queues.js:79:11)

My code so far (all of myApp.js)

require("dotenv").config();
const mongoose = require("mongoose");

mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true });

const Schema = mongoose.Schema;
const personSchema = new Schema({
  name: {type: String, required: true},
  age: Number,
  favoriteFoods: [String]
});

const Person = mongoose.model("Person", personSchema);

const createAndSavePerson = (done) => {
  const person = new Person({
    name: "Osman Zakir",
    age: 21,
    favoriteFoods: [
      "Burgers",
      "Pizza",
      "Pasta",
      "Meat and Chicken Curries"
    ]
  });
  person.save((err, person) => {
    if (err) {
      console.log(err);
    }
    console.log(`${person.name} saved to database`);
  });
  done(null, person);
};

const createManyPeople = (arrayOfPeople, done) => {
  done(null /*, data*/);
};

const findPeopleByName = (personName, done) => {
  done(null /*, data*/);
};

const findOneByFood = (food, done) => {
  done(null /*, data*/);
};

const findPersonById = (personId, done) => {
  done(null /*, data*/);
};

const findEditThenSave = (personId, done) => {
  const foodToAdd = "hamburger";

  done(null /*, data*/);
};

const findAndUpdate = (personName, done) => {
  const ageToSet = 20;

  done(null /*, data*/);
};

const removeById = (personId, done) => {
  done(null /*, data*/);
};

const removeManyPeople = (done) => {
  const nameToRemove = "Mary";

  done(null /*, data*/);
};

const queryChain = (done) => {
  const foodToSearch = "burrito";

  done(null /*, data*/);
};

/** **Well Done !!**
/* You completed these challenges, let's go celebrate !
 */

//----- **DO NOT EDIT BELOW THIS LINE** ----------------------------------

exports.PersonModel = Person;
exports.createAndSavePerson = createAndSavePerson;
exports.findPeopleByName = findPeopleByName;
exports.findOneByFood = findOneByFood;
exports.findPersonById = findPersonById;
exports.findEditThenSave = findEditThenSave;
exports.findAndUpdate = findAndUpdate;
exports.createManyPeople = createManyPeople;
exports.removeById = removeById;
exports.removeManyPeople = removeManyPeople;
exports.queryChain = queryChain;

Here’s the Repl.it link.

My browser information:

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36 Edg/88.0.705.74.

Challenge: Create and Save a Record of a Model

Link to the challenge:

I need some info on how to use done and whether or not I’m creating and saving the document correctly. Thanks in advance for any help.

I just changed the code to this:

const createAndSavePerson = (done) => {
  const person = new Person({
    name: "Osman Zakir",
    age: 21,
    favoriteFoods: [
      "Burgers",
      "Pizza",
      "Pasta",
      "Meat and Chicken Curries"
    ]
  });
  person.save((err, person) => {
    if (err) {
      console.log(err);
      return done(err);
    }
    console.log(`${person.name} saved to database`);
  });
  return done(null, person);
};

for createAndSavePerson (notice the return done(...) lines) but it still gives me the same error as before.

I really need some help here. I tried Googling about done but found nothing helpful yet. I’ll keep looking for now.

I think the problem is where you’ve placed the done(). If it’s outside the save() function’s callback, it can’t access the data or error of the save function, so in this case, it’s trying to return the person defined earlier with new Person() and not the returned document from save. This causes the error you see from server.js because it expects a document with data it can use to eventually call remove(), and it can’t. You may want to use different variable names to differentiate the models, schemas, and documents of same type to avoid confusion.

Since done() is just a standard callback holding a place for a function supplied by the caller, you can use the done(error) signature in your save() callback in the error handling part and the done(null, person) signature (no error) in the data returning part of the callback.

Thanks for the info. I’ll do that.