Author: Dunk
Translator: Crazy Technology House
Original: https://nikodunk.com/how-to-c...
Reproduction is strictly prohibited without permission
Before I finish electrade In addition to their work, they helped a friend's team finish their project. Recently, we hope to build a Craiglist-style anonymous e-mail relay for this project, which includes "serverless" Google Firebase Function (the same as AWS Lambda, Azure Function, etc.). So far, I've found it easier to think about handling asynchronous operations with. then() callbacks, but I want to use async/await here because it reads more clearly. I find most articles about linking multiple functions useless because they tend to publish incomplete demo code that is copied and pasted from MSDN. There are some pitfalls in async/await that are difficult to debug, because I have encountered all these pitfalls, so I will publish my complete code here and explain my learning process.
This is the working code that connects multiple functions, waits to solve all the problems, and then the N sends the results. The main mistakes are:
- Each async function myFunction () {your code here >} declaration automatically wraps the entire asynchronous function code (that is, < your code here >) in a new Promise, then converts it to return x and adds resolve (x) to the code. But you also need to wait outside it (let y = await myFunction()) or it won't actually wait. This debugging is very annoying.
- In a cloud function, you must send a response with res.send(), otherwise the function will think it failed and run it again.
The following code does these things:
- We have two normal synchronization functions getFieldsFromRequest() and extractCourseIdFromEmailAddress() -- no problem here.
- Then we need the async function getEmailOfCourseWithCourseId() to get the e-mail address of the course from Firestore. We don't know how long it takes to get content from Firestore, so it's async, and we need to run the next two functions and return (or promise parse) courseEmail.
- The next two functions, saveToCloudFirestore() and sendEmailInSendgrid(), cannot run and return courseEmail before getEmailOfCourseWithCourseId(), otherwise they will think courseEmail is undefined, which makes everything worse. Through the function getEmailOfCourseWithCourseId() above awaiting and passing courseEmail, these functions (and if operators) will wait until this happens (that is, it has been resolved) and run again.
- Finally, before running saveToCloudFirestore () and sendEmailInSendgrid() and returning their values, we cannot send res.send(), otherwise our entire cloud function will be interrupted before the work is completed. To do this, we save the saveToCloudFireStore () and sendEmailInSendgrid() responses (what they return) into variables, the only purpose of which is to mark when the above functions are completed. This replaces. then(): It waits for the two variables (savedToCloud and sentEmail) to "arrive" (their Promise has been resolved) and then runs res.send().
- For ease of reading, I've deleted try/catch packaging that you should do in practice. You should never catch errors, but deleting them will make the async/await concept easier to understand.
// this is the cloud function you can call over HTTP. It is basically for email relay: // it gets an email from sendgrid, parses the fields, looks up the real email with the courseId, // saves to FireStore and sends and email with sendgrid. // Finally, it sends a res.send() to end the cloud function // {* import a bunch of shit *} // main function exports.emailFunction = functions.https.onRequest(async (req, res) => { let fields = getFieldsFromRequest(req); // sync let courseId = extractCourseIdFromEmailAddress(fields); // sync let courseEmail = await getEmailOfCourseWithCourseId(courseId); // async let savedToCloud = await saveToCloudFirestore(fields, courseEmail, courseId); // async let sentEmail = await sendEmailWithSendgrid(fields, courseEmail); // async res.status(200).send(savedToCloud, sentEmail); // Once sentEmail and saveToCloud have been returned (aka promises have been resolved, aka their functions have been run), res.send() will run so Firebase/SendGrid know that func worked. }); // Helper functions below function getFieldsFromRequest(req) { // sync let fields = readTheFieldsFromReqWithBusboy(req) return fields; } function extractCourseIdFromEmailAddress(fields) { // sync let courseId = fields.to.substring(0, fields.to.indexOf('@')); return courseId; } async function getEmailOfCourseWithCourseId(courseId) { // async important let courseData = await database.get(courseId) let courseEmail = courseData.email; return courseEmail; // due to function being labeled async above, this is the equivalent of wrapping the whole function in 'return new Promise(resolve) => {}' and then returning a 'resolve(result)' } async function sendEmailWithSendgrid(fields, courseEmail) { // async important let msg = {to: courseEmail, from: fields.from, text: fields.text} let sentEmail = await sendgrid.send(msg) return sentEmail; // due to function being labeled async above, this is the equivalent of wrapping the whole function in 'return new Promise(resolve) => {}' and then returning a 'resolve(result)' } async function saveToCloudFirestore(fields, courseEmail, courseId) { // async important let savedToCloud = await database.add(fields, courseEmail, courseId) return savedToCloud; }
Finally, try {catch {} wraps the last three asynchronous functions and main functions to catch errors. In addition, database code cannot be copied intact -- it's only for illustrative purposes!
Wechat Public Number: Front-end Pioneer
Welcome to scan the two-dimensional code, pay attention to the public number, and push you fresh front-end technical articles every day.
Welcome to continue reading other highly praised articles in this column:
- Deep Understanding of Shadow DOM v1
- Step by step teach you how to use WebVR to implement virtual reality games
- Thirteen Modern CSS Frameworks to Improve your Development Efficiency
- Fast Start Bootstrap Vue
- How does the JavaScript engine work? Everything you need to know from call stack to Promise
- WebSocket Reality: Real-time Communication between Node and React
- 20 interview questions about Git
- In-depth analysis of Node.js console.log
- What exactly is Node.js?
- Build an API server with Node.js in 30 minutes
- Object Copy of Javascript
- Programmers earn less than 30K a month before they are 30 years old. Where to go?
- 14 Best JavaScript Data Visualization Libraries
- Eight top-level VS Code extension plug-ins for the front end
- Complete guide to Node.js multithreading
- Four Solutions and Implementation of Converting HTML to PDF