CPNT 262 Day 21 - Mongoose with async/await and try/catch
Housekeeping
- Assignment 3 marks published.
Trophy of the day
- Assignment 3 refactored to use async/awaitandtry/catch
1. Promises with async/await
Materials
- MDN: Making asynchronous programming easier with async and await
- Demo Starter Code: Fetch Random Dog
Key Takeaways
- 
async/awaitis a newer and alternative syntax for Promises, which function the same way as with.then()and.catch().
- 
Only 95% of browsers (as of Nov 2021) understand async/awaitbut all updated Node servers understand it. You don't see.then()and.catch()very often on the server side.
- 
In order to use the awaitkeyword, you need to wrap your code inside a function defined with theasynckeyword.const hello = async function() {
 // `await` can now be used inside this function
 return "Hello"
 };
- 
awaitis used to "pause" your code when invoking a function that returns a promise, likefetch()ormodel.find()and.then().const myFetch = async function() {
 const response = await fetch('/api/characters/5');
 const data = await response.json();
 document.querySelector('.container').textContent = data.name;
 }
 myFetch();
- 
.catch()works the same way when you useasync/awaitbut you define it when you invoke theasyncfunction:// Define an async function
 const myFetch = async function() {
 let response = await fetch('/api/characters/5');
 // An exception thrown by the developer
 if (!response.ok) {
 throw new Error(`HTTP error! status: ${response.status}`);
 }
 let data = await response.json();
 document.querySelector('.container').textContent = data.name;
 }
 // Invoke an async function
 myFetch().catch(function(error) {
 console.log(error);
 });- Note: fetch()only throws an exception when there's a network error (i.e. domain not found), not when there's a404 Not Founderror.
 
- Note: 
2. Exceptions and try/catch blocks
Terminology
- Exceptions
- An error that produces an error object that can be "handled" by the Javascript engine. Exceptions can be "thrown" when Javascript encounters a runtime error or if the developer explicitly throws an exception.
- Throwing an Exception
- Producing an error object.
- Exception Handling
- Doing something with an exception instead of moving to the next statement in the code. Also called "catching" errors.
Materials
Key Takeaways
- 
Exceptions can only be thrown by runtime errors. Syntax errors cannot throw exceptions because the code can't run in the first place. 
- 
A common way to handle exceptions is to wrap your code in a try/catchblock.
- 
With asynchronous code, try/catchis often used withasync/awaitinstead of using a.catch()block.// Define an async function
 const myFetch = async function() {
 try {
 let response = await fetch('/api/characters/5');
 
 let data = await response.json();
 document.querySelector('.container').textContent = data.name;
 } catch(error) {
 console.log(error);
 }
 }
 // Invoke an async function
 myFetch();
- 
The developer can throw Exceptions explicitly with throw new Error():// Define an async function
 const myFetch = async function() {
 try {
 let response = await fetch('/api/characters/5');
 
 let data = await response.json();
 document.querySelector('.container').textContent = data.name;
 } catch(error) {
 console.log(error);
 }
 }
 // Invoke an async function
 myFetch();
Activity
Refactor Assignment 3 so that it uses async/await with a try/catch block instead of .then()/.catch().
3. Mongoose GET requests with async/await
Materials
- Prep
- Mongoose with Promises: CRUD Operations with Mongoose and MongoDB Atlas
- Reference: Mongoose Queries in the mongoose documentation.
 
- Gist: Read MongoDB data with Mongoose and Express
- Demo Starter Code:
Key Takeaways
- 
Since all our Mongoose code will be inside a function passed to our method handler, we place the asynckeyword in front of it.app.get('/api/cats', async (request, response) => {
 response.send('This is asynchronous!');
 })
- 
Once your Mongoose code is inside an asyncfunction, you use theawaitkeyword whenever you invoke a Mongoose method (because all Mongoose functions use Promises when you don't pass it a callback function as an optional parameter).const catSchema = new mongoose.Schema({name: String})
 const Cat = mongoose.model('Cat', catSchema);
 app.get('/api/cats', async (request, response) => {
 const data = await Cat.find();
 response.send(data);
 })
- 
Since app.get()invokes our callback function for us, it's difficult (impossible) to attach a.catch()method (for Promises) on the end of it. Instead, we use atry/catchblock to handle any problems we might have with Atlas:const catSchema = new mongoose.Schema({name: String})
 const Cat = mongoose.model('Cat', catSchema);
 app.get('/api/cats', async (request, response) => {
 try {
 const data = await Cat.find();
 response.send(data);
 } catch(error){
 console.log('Caught an error!', err)
 response.send({error: 'Uh oh, there was an error'})
 }
 })
Lab Time
- Trophy of the day
- Assignment 5
- Final Project
Prep
Introduction to CRUD and Mongoose
- Using Callbacks: NodeJs CRUD Operations Using Mongoose and MongoDB Atlas
- Using Promises: CRUD Operations with Mongoose and MongoDB Atlas
- Reference: Mongoose Queries in the mongoose documentation.
