DOUG STEVENSON: Welcome back to part 2
in this series on using async/await
with Cloud Functions for Firebase.
So how do you make use of async/await syntax
in TypeScript or ECMAScript 2017 to write better Cloud Functions
code?
Well, in my last video, you learned
the basics of async/await to work with promises.
The code samples there didn't have anything
to do with Cloud Functions directly,
but today I'll show you how to apply what you learned.
If you haven't already watched that video,
do it now because you'll need that information
to follow along here.
As you know, the Async keyword indicates that a function
always returns a promise.
And inside an Async function, you
can use the Await keyword to pause
that function until some other promise becomes fulfilled
or rejected and get a hold of its result.
You can use this syntax in your Cloud Functions code
to work with the promises returned by the Firebase Admin
SDK and other APIs you might use.
What I'll do today is refactor some existing Cloud Functions
code I wrote for my earlier series on promises.
Let's jump in there and get to it.
Here's the HTTP function I wrote earlier
that fetches the current weather conditions
for the city of Boston that's stored
in a document in Firestore.
It uses the Firebase Admin SDK to access Firestore.
It creates a reference to a document
in the Cities Weather Collection for the city of Boston.
Then it uses the Get method on that reference.
Remember that Get is asynchronous and returns
a promise that will become fulfilled when the document
snapshot is available.
To get a hold of that, it calls the Then method
on that promise, and passes an anonymous callback function,
which receives the snapshot.
The function pulls the data out of the snapshot
and sends it to the caller as JSON, or if there's an error,
the chained Catch callback will be invoked.
The function passed to Catch receives the error object.
And that's what's used to send an HTTP error
response to the caller.
This one is easy to refactor to use async/await.
First, I need to mark this entire anonymous function
passed to onRequest as async.
This will let me use await inside of it.
Then I'll create an empty Try Catch.
I'll move the document fetch into it,
and I'll use the Await keyword to pause my Async function
until the snapshot is ready.
To get that snapshot, all I have to do
is use the Await keyword before the promise is returned by Get.
Await unwraps the snapshot from the promise,
and I can assign it to a constant.
Now, I'll move the rest of the code that
deals with the snapshot into the Try block.
And I'll move the code from the old Catch callback
into the new Catch block.
And after removing some old code, the refactoring is done.
This function was pretty straightforward to refactor
to use async/await.
In my opinion, the code is easier to read now.
With async/await, there's fewer functions and parentheses
to deal with.
Now let's take a look at another function from a prior video.
This is a Firestore trigger that fires whenever the Boston City
Weather document is updated with new weather conditions.
When that happens, it takes the updated contents
of the document, uses it to build
a payload for a notification, and sends it
to a Firebase Cloud Messaging topic for mobile applications
to receive.
The important thing to remember here
is that Firestore triggers need to return a promise
to indicate when all the async work is complete.
You can see that since the topic returns a promise that
becomes fulfilled when the message is sent,
and that promise is returned from the function here.
So what can we do to refactor this function
to use async/await?
Well, in my opinion, I wouldn't change a thing here.
If all you want to do is return a single promise
from a function, then just do that.
No need to type in extra code.
I could mark this function async,
then use await to pause it when send to topic completes.
But that doesn't really add any value here,
because I'm not using its results.
If the use of async/await doesn't improve the readability
of your code, just skip it.
OK.
Let's take a look at one more function from a prior video.
There's a lot going on in this HTTP function,
so I'll go over it real quick.
It gets a document from Firestore
that has a list of cities in the greater Boston area.
For each city in that list, it gets another document
that contains the current weather
conditions in that city.
The promise for each document fetch
is collected into an array, and promise.all
is used to create a new promise that's
fulfilled after all the others are fulfilled.
An array of snapshots of documents
is delivered to the next Then callback, where
their data is collected into another array
and sent to the client as JSON.
To refactor this to use async/await,
I'll do like before and mark the function async,
then create an empty Try Catch.
I'll move the first document get into the Try block,
and use await to unwrap the snapshot from the promise.
Then I'll move the rest of the code
from the first Then callback.
Now, I've got all these promises collected here,
and the call to promise.all to combine them
into a single promise.
Let's talk about that for a moment.
Async/await provides a syntax for you
to express sequences of work, one
after another, as you've seen here.
But this bit of code is trying to kick off
multiple items of work all at the same time,
possibly in parallel.
For situations like this, when you
want to wait on pending work represented
by multiple promises, async/await
can't make things any easier for you.
You have to keep using promise.all for that.
However, you can use await on the promise it returns.
Instead of returning that promise
to the next Then callback, I'll use await here again
and capture the resulting array of snapshots in a constant.
Then I'll move the rest of the code into the Try block.
And lastly, I'll move the code from the Catch callback
into the new Catch block, and that's it.
Async/await can be a great way for you
to write cleaner code when dealing with promises.
Use them where they make sense, but don't
feel like you have to.
You can expect to see me use them
in future videos about Cloud Functions for Firebase.
And to get notified about those videos,
you should subscribe right here to the Firebase channel
on YouTube.
See you next time.
[MUSIC PLAYING]