Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using mongoose promises with async/await

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';     });   }, 
like image 787
Patrick Connors Avatar asked Sep 27 '17 20:09

Patrick Connors


People also ask

Can we use promise and async await together?

Async/Await is used to work with promises in asynchronous functions. It is basically syntactic sugar for promises. It is just a wrapper to restyle code and make promises easier to read and use. It makes asynchronous code look more like synchronous/procedural code, which is easier to understand.

Does Mongoose support async await?

Mongoose queries are not promises. They have a . then() function for co and async/await as a convenience. If you need a fully-fledged promise, use the .

How do you use await With mongoose?

To use async-await syntax, you need to write an asynchronous function, as shown below: const mongoose = require('mongoose'); const server = '127.0. 0.1:27017'; // REPLACE WITH YOUR OWN SERVER const database = 'test'; // REPLACE WITH YOUR OWN DB NAME const connectDB = async () => { try { await mongoose.

Is async await the same as promises?

Promise creation starts the execution of asynchronous functionality. await only blocks the code execution within the async function. It only makes sure that the next line is executed when the promise resolves. So, if an asynchronous activity has already started, await will not have any effect on it.

What is async await in mongoose?

Async/await makes interacting with mongoose cursors much more elegant. While you still can use cursors as a stream with async/await, it's much more elegant to use the next () function.

How do you use promises without async and await keywords?

There are two rules to follow when using promises without async/await keywords: 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.

Can you use async in mongoose cursors?

Mongoose cursors also have a neat eachAsync () function that lets you do some rudimentary functional programming with async/await. The eachAsync () function executes a (potentially async) function for each document that the cursor returns.

What is the purpose of the async/await function?

"The purpose of async/await functions is to simplify the behavior of using promises synchronously and to perform some behavior on a group of Promises. Just as Promises are similar to structured callbacks, async/await is similar to combining generators and promises."


2 Answers

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:

  1. A function is asynchronous if it returns a Promise
  2. 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.

like image 107
Tamas Hegedus Avatar answered Sep 28 '22 02:09

Tamas Hegedus


You need to return your Promise.

  • Currently, you are awaiting on a function that returns undefined.
  • await only actually "waits" for the value if it's used with a Promise.
  • Always keep in mind that you can only await Promises or async functions, which implicitly return a Promise1.

orderEmployees: (companyID) => {   return User.find({ company:companyID }).exec() } 

Also really important, you should throw instead of return in your .catch handler. Returning from within a .catch handler will cause the promise chain to trigger it's .then instead of it's .catch thus breaking the error handling chain.

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.

Error conditions should throw the error, not return it.


1 You can also await non-Promises, but only for values that are evaluated synchronously.

like image 34
nicholaswmin Avatar answered Sep 28 '22 01:09

nicholaswmin