I am have just finished the lesson https://www.freecodecamp.org/learn/apis-and-microservices/mongodb-and-mongoose/perform-classic-updates-by-running-find-edit-then-save and figured it out. Below is the solution. I had trouble working it out though because on the final line of the code I was trying to use docs.save() instead of docs.save([callback]). The reason I was trying to use it without a callback is simply because I wanted to, and the documentation stated that specifying a callback was optional. According to the documentation for this command here (and almost all other node commands that support callback) callbacks are optional so I want to understand why it wouldnât work for me. Below this code (which uses the callback) I will show the code i used without a callback which failed.
var findEditThenSave = function(personId, done) {
var foodToAdd = 'hamburger';
Person.findById(personId, function (err, docs) {
if (err) return (err);
docs.favoriteFoods.push(foodToAdd);
console.log(docs);
docs.save(function (err, data) {
if (err) return (err);
done( null, data);
});
});
};
But it didnât work. Should it have or am I misunderstanding how to use this api without a callback?
I even tried console.log(docs.asve()) to rule out if Iâd made other mistakes in my code and it didnât work either. It said something about a promise??
You need to wait for a data from Mongo and then to pass it to done, right? When using like this:
Youâre passing a promise for the data, not the data itself. Apparently done function isnât happy with that
So the only way is to wait for the data. And here you have 3 options:
Callback
Promise.then()
docs.save().then((data) => done(null, data));
async function
Person.findById(personId, async (err, docs) => {
if (err) return (err);
// btw, starting from next line you're entering territories of black magic
// and probably should not do that outside curriculum
docs.favoriteFoods.push(foodToAdd);
const data = await docs.save();
done(null, data);
});
So am I right in saying then that the docs.save() is an async function?
I have came to this conclusion due to the fact that it doesnât wait for the results (which is a characteristic of a callback or async function). To elaborate on this - before I started looking at Node.js my understanding of normal coding was âblockingâ and non async. When I then started learning Node I found the concept of non blocking code. But, my understanding of this is that if you want some code to be non blocking you had to write it a specific way, namely it being a callback function or async function (or something else I havenât learnt yet). When I saw docs.save() I thought it would natively âblockâ, and by adding an optional callback (accord to itâs doco) this would turn it into the ânon-blockingâ equivalent - in other words my understanding is that all code is âblockingâ by default until you define it otherwise with a CB or async function (is this understanding correct?)
From what you have described (and demonstrated) of docs.save() it appears to be non- blocking, therefore my conclusion is that it must be an async function. Would this assessment be correct?
Yes, this is correct. If you donât provide callback, it returns promise. You also have to note that itâs a custom Mongoose logic, not every function that expect callback (including in NodeJS) would do that. This is just that way Mongoose API works, they provide backward compatibility for âoldâ code while giving options for writing ânewâ code.