I'm trying to get the hang of using Mongoose promises with the async/await functionality of Node.js. When my function printEmployees
is called I want to save the list of employees which are queried by the orderEmployees
function. While, the console.log
statement inside orderEmployees
returns the expected query, the console.log
inside of printEmployees
returns undefined
, suggesting that I'm not returning the promise correctly.
I'm new to promises so entirely possible that I'm not correctly understanding the paradigm... any help is much appreciated.
printEmployees: async(company) => {
var employees = await self.orderEmployees(company);
// SECOND CONSOLE.LOG
console.log(employees);
},
orderEmployees: (companyID) => {
User.find({company:companyID})
.exec()
.then((employees) => {
// FIRST CONSOLE.LOG
console.log(employees);
return employees;
})
.catch((err) => {
return 'error occured';
});
},
You need to return
your Promise
, otherwise you are awaiting on a function that returns undefined
.
orderEmployees: (companyID) => {
return User.find({ company:companyID }).exec()
}
Currently, you're awaiting a non-Promise so next-line code will run immediately; before the Promise you really want to await actually resolves.
Also really important, you should throw
instead of return
in your .catch
handler. Or better yet, don't include .catch
at all and let the the actual error bubble up the promise chain, instead of overriding it with your own non-descriptive 'error occured'
message.
In order to make orderEmployees
behave like async functions, you have to return the resulting promise. There are two rules to follow when using promises without async/await
keywords:
- A function is asynchronous if it returns a
Promise
- If you have a promise (for example returned by an async function) you must either call
.then
on it or return it.
When you are using async/await
then you must await
on promises you obtain.
This said you will notice that you do not return the promise generated inside orderEmployees
. Easy to fix, but its also easy to rewrite that function to async too.
orderEmployees: (companyID) => {
return User.find({company:companyID}) // Notice the return here
.exec()
.then((employees) => {
// FIRST CONSOLE.LOG
console.log(employees);
return employees;
})
.catch((err) => {
return 'error occured';
});
},
or
orderEmployees: async(companyID) => {
try {
const employees = await User.find({company:companyID}).exec();
console.log(employees);
return employees;
} catch (err) {
return 'error occured';
}
},
PS: the error handling is somewhat flawed here. We usually do not handle errors by returning an error string from a function. It is better to have the error propagate in this case, and handle it from some top-level, UI code.
You are not returning a Promise from orderEmployees.
printEmployees: async(company) => {
var employees = await self.orderEmployees(company);
// SECOND CONSOLE.LOG
console.log(employees);
},
orderEmployees: (companyID) => {
return User.find({company:companyID})
.exec()
.then((employees) => {
// FIRST CONSOLE.LOG
console.log(employees);
return employees;
})
.catch((err) => {
return 'error occured';
});
},
You need to return a Promise
from orderEmployees
orderEmployees: companyId => User.find({ companyId }).exec()
If you want to do some error handling or pre-processing before you return then you can keep your code as is but just remember to return the result (promises are chainable).