분류 javascript

Await / Async를 사용하여 Javascript의 여러 함수를 올바르게 연결하는 방법

컨텐츠 정보

  • 조회 206 (작성일 )

본문

선거를 만들고 운영하는 주요 업무 옆에 나는 친구 팀이 그들의 프로젝트를 도와줍니다. 

최근 이 프로젝트를 위해 "서버 없는"Google Firebase 기능 (AWS Lambda, Azure Functions 등)을 사용하여 Craiglist 스타일의 익명 이메일 릴레이를 구축하려고 했습니다. 지금까지 .then() 콜백을 사용하여 비동기 작업을 처리하는 것이 더 쉽게 생각할 수 있지만 읽기가 훨씬 깨끗하기 때문에 여기에서 async / await를 사용하고 싶었습니다. 

MSDN에서 복사 / 붙여 넣은 불완전한 데모 코드를 게시하는 경향이 있기 때문에 여러 기능을 연결하는 데 도움이 되는 대부분의 기사가 도움이 되었습니다. async / await에는 디버그 하기 어려운 함정이 몇 가지 있으며, 그중 하나에 빠지기 때문에 여기에 전체 코드를 게시하고 내 학습 내용을 설명하므로 필요하지 않습니다.


https://nikodunk.com/how-to-chain-functions-with-await-async/ 


다음은 여러 함수를 연결하고 모든 것이 해결되기를 기다린 다음 결과를 전송하는 작동 코드입니다. 주요 실수는 다음과 같습니다.


  1. 모든 비동기 함수 myFunction() {<your code here>} 선언은 자동으로 전체 비동기 함수의 코드 (예 : <your code here>)를 새 약속에 래핑하고 코드 내의 모든 리턴 x를 resolve(x)로 바꿉니다. 그러나 여전히 외부에서 기다려야 합니다 (예 : y = amyFunction()을 기다리십시오) 그렇지 않으면 실제로 기다리지 않습니다. 이 문제를 해결하는 것은 매우 성가신 일입니다.
  2. 참고 사항 – 클라우드 함수에서 res.send()로 응답을 보내야 합니다. 그렇지 않으면 함수가 실패했다고 가정하고 다시 실행합니다. 이것은 모든 것이 실행되거나 약속이 취소되면 분명히 발생합니다.

아래 코드는


  • 우리는 getFieldsFromRequest()와 extractCourseIdFromEmailAddress() –2 개의 일반적인 동기화 함수를 가지고 있습니다.
  • 그런 다음 Firestore에서 코스의 이메일 주소를 가져 오는 비동기 함수 getEmailOfCourseWithCourseId()가 있습니다. Firestore에서 물건을 가져 오는 데 시간이 얼마나 걸리는지 알 수 없으므로 비 동기화 되고 다음 두 가지 기능을 실행하는 데 필요한 과정 이메일로 돌아갑니다.
  • 다음 두 함수 인 saveToCloudFirestore() 및 sendEmailInSendgrid()는 getEmailOfCourseWithCourseId()가 실행되고 courseEmail을 리턴하기 전에 실행되지 않아야 합니다. 위의 getEmailOfCourseWithCourseId() 함수를 기다리는 courseEmail을 전달하면 이러한 함수 (및 if 연산자)는 해당 상황 (일명 약속이 해결됨)까지 기다렸다가 실행합니다.
  • 마지막으로, saveToCloudFirestore() 및 sendEmailInSendgrid()가 실행되어 값을 반환 할 때까지 res.send()를 보내면 안됩니다. 그렇지 않으면 작업이 완료되기 전에 전체 클라우드 함수가 중단됩니다. 이를 위해 saveToCloudFireStore() 및 sendEmailInSendgrid() 응답 (반환되는 항목)을 위 함수가 완료된 것으로 표시 할 목적으로 만 사용하는 변수에 저장합니다. 이것은 어떤 의미에서 .then()을 대체합니다.이 두 변수 (savedToCloud 및 sentEmail)가 "도착"(일명 약속이 해결 될 때까지) 기다린 다음 res.send()를 실행합니다.
  • 가독성을 위해 실제로 수행해야 할 try / catch 래핑을 제거했습니다. 오류를 잡아서는 안되지만 오류를 제거하면 비동기 / 대기 개념을 보다 쉽게 ​​이해할 수 있습니다.

// 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; } 


다시, 3 개의 마지막 비동기 함수와 try {} catch {}의 기본 함수를 랩하여 오류를 포착하십시오. 또한 데이터베이스 코드는 이와 같이 복사 할 수 없으며 단지 설명을 위한 것입니다. 경고를 받았습니다!