2

I have 3 async functions:

ToDoItem.deleteMany({}); // deletes entire collection
ToDoItem.insertMany(itemArray); // adds new items to collection
ToDoItem.find({}); // finds all the items in the collection

This code alone doesn't work well, as they do not follow a consistent order. I.e. the insertion might happen before deletion, which I do not want.

I can use callbacks to chain them together (callback hell), and I can also use .then to chain them together, as they return promises. However, I would like to use async/await.

Additionally, these functions can be given optional callbacks, for instance:

ToDoItem.find({}, (data) => { 
  console.log(data); 
});

This is useful as I want to see all the data in my DB that matches the query {} (which is all items).

However I can't figure out how to access these callbacks by using async and await. I can do it via callbacks or .then, but the code is more messy. Is there a way to do this?

Edit:

As per Bergi's reply, I have edited my code as such:

async function setupDatabase() {
  const deleteResult = await ToDoItem.deleteMany({});
  console.log("Items deleted. Delete result:")
  console.log(deleteResult);

  const insertResult = await ToDoItem.insertMany(defaultItems);
  console.log("Items have been added successfully");
  console.log(insertResult);

  const findResult = await ToDoItem.find({});
  console.log("Here are the items:")
  console.log(findResult);
}

Am I correct in thinking that:

  1. deleteResult will now evaluate to be either the deletion confirmation (if successful) or the error (if rejected). And similarly with insertResult and findResult?

  2. What do I do if I want to return the collection found by .find({}), as the function setupDatabase is now async and returns a promise.

  3. If 1) is correct, how do I separate out when I'm getting an error and when I'm getting a result?

As per Konrad's response, I have done the following:

async function setupDatabase() {
  const deleteResult = await ToDoItem.deleteMany({});
  console.log("Items deleted. Delete result:")
  console.log(deleteResult);

  const insertResult = await ToDoItem.insertMany(defaultItems);
  console.log("Items have been added successfully");
  console.log(insertResult);

  const findResult = await ToDoItem.find({});
  console.log("Here are the items:")
  console.log(findResult);

  return findResult;
}


app.get("/", function(req, res) {
  (async function() {
    const objectList = await setupDatabase();
    let dataList = [];
    
    for (element of objectList) {
      dataList.push(element.todo);
    }
    res.render("list", {listTitle: "Today", newListItems: dataList});
  }());

My idea was to return the findResult inside the setupDatabase function. But this is actually a promise since the function is async, so I wrapped it in an IIFE inside the .get. I then iterated over this list and created dataList which has the actual data I want to render.

5
  • deleteResult will now evaluate to be either the deletion confirmation (if successful) or the error (if rejected) - no, errors will be thrown, if you want to handle them, you have to catch them Commented Nov 17, 2022 at 22:10
  • What do I do if I want to return the collection found by .find({}) - you use return statement and in the called you can handle the promise as usuall Commented Nov 17, 2022 at 22:10
  • Konrad, thank you for your responses. I have to sit on the first one for a bit. The second one I made an edit in my post if you are able to take a look. I think I got it (the code works) I just wanted to verify if you had any notes or concerns. Thank you. Commented Nov 17, 2022 at 22:28
  • FYI, on StackOverflow you should NOT edit your question to show the solution. Answers belong in answers, not in questions. If the provided answers don't show the answer you want, you can post your own answer. Commented Nov 18, 2022 at 0:33
  • Thanks jfriend00, I couldn't figure out that functionality as I was new, but I see it now. Commented Nov 18, 2022 at 1:19

1 Answer 1

2

You don't use async/await with callbacks.

You use await with promises, and you should not mix those with callbacks - in particular, MongoDB does not return a promise when you pass a callback. You need to write

await ToDoItem.deleteMany({}); // deletes entire collection
await ToDoItem.insertMany(itemArray); // adds new items to collection
const data = await ToDoItem.find({});

Am I correct in thinking that [the await expression] will now evaluate to be either the deletion confirmation (if successful) or the error (if rejected)?

No. The result of the await is the successful promise fulfillment value. In case of a promise rejection, the error is thrown as an exception, you can handle it with a try/catch block.

What do I do if I want to return the collection found by .find({}), as the function setupDatabase is now async and returns a promise.

The async/await syntax doesn't change anything. The function was asynchronous before, and it's impossible to immediately return the result, regardless whether you'd use callbacks or promise .then() chaining syntax or await syntax. Returning a promise is actually desirable - the caller just has to wait for it!

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, that makes sense. I have created an edit in my post to reflect my updated code. I also wrote two follow-up questions in there as well if you are able to check them out. Thanks for your time in writing this reply and answer!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.