비동기 대기: 시간의 60%, 매번 작동

모두 과대 광고 열차에 탑승했습니다.



핫 테이크: async await는 모든 것에 적합하지 않습니다.

사람들이 이런 글을 쓰는 걸 봤을 때:

const printF = async () => {
  try {
    const a = await getA()
    const b = await getB(a)
    const c = await getC(b)
    const d = await getD(c)
    const e = await getE(d)
    const f = await getF(e)
    console.log(f)
  } catch (err) {
    console.error(err)
  }
}


이에 대한 대체품으로:

const printF = () =>
  getA()
   .then(getB)
   .then(getC)
   .then(getD)
   .then(getE)
   .then(getF)
   .then(console.log)
   .catch(console.error)


잘못된 방향으로 나아가는 큰 발걸음이라고 생각했습니다. 약간의 이점을 위해 많은 상용구를 추가했습니다. 나는 몇 년 동안 try-catch를 했고 돌아가고 싶지 않았습니다!

async await만 사용하는 직장 ​​친구들에게 몇 가지 심각한 질문이 있었습니다.



Do we really love async await, or are we just saying that because we saw it?





램프를 사랑할 때.



위의 예는 실제로 꽤 비정형적이었습니다. 모든 것에 대해 async/await가 필요하지 않다는 점을 지적하기 위한 것입니다.

항상 "더 읽기 쉬운"것은 아니며 동기식 코드처럼 보입니다.

실제로 사람들은 printF에 돈을 지불하지 않습니다. 대신, 나는 비밀리에 문자열을 다른 문자열로 바꾸는 생계를 위해 웹 사이트를 구축합니다.

따라서 이 문자열을 얻을 때:

'https://www.<some-website>.com/people/ryan'


나는 그것을 다음 문자열로 바꿉니다.

<div>
  <h1>Ryan Haskell-Glatz</h1>
  <section>
    <h3>Posts</h3>
    <ul>
      <li>Elm is neat.</li>
      <li>Promises are neat.</li>
      <li>Saying neat is neat.</li>
    </ul>
  </section>
</div>


그러나 때때로 내 문자열이 데이터베이스에 있습니다.

// MongoDB
{
  people: [
    { _id: 1, slug: 'ryan', name: 'Ryan Haskell-Glatz' },
    // ... more people
  ],
  posts: [
    { _id: 12, slug: 'elm-is-neat', title: 'Elm is neat.', author: 1 },
    { _id: 13, slug: 'promises-are-neat', title: 'Promises are neat.', author: 1 },
    { _id: 14, slug: 'saying-neat-is-neat', title: 'Saying neat is neat.', author: 1 },
    // ... more posts
  ]
}


따라서 내 Javascript 함수는 다음과 같이 보입니다.

const mongoose = require('mongoose')

const getPosts = (person) =>
  mongoose.model('posts')
    .find({ author: person })
    .select('title')
    .lean()
    .exec()

const getPerson = (slug) =>
  mongoose.model('people')
    .findOne({ slug })
    .select('name')
    .lean()
    .exec()
    .then(person => person || Promise.reject(`Couldn't find a person with slug: ${slug}`))

const getPeopleDetailPage = (req) =>
  getPerson(req.params.slug)
    .then(person =>
      getPosts(person)
        .then(posts => ({ person, posts }))
    )


더 멋지게 만들기


getPostsgetPerson 모두 괜찮습니다. async await는 아무 것도 개선하지 않습니다.

.then 함수를 getPeopleDetailPage에 어떻게 중첩시켰는지 확인하세요. 뾰족한 삼각형 콜백 지옥 같은 것 같습니다.

물건을 중첩시킨 이유는 personposts 모두에 대한 액세스가 필요했기 때문입니다.

마지막 함수를 다시 작성해 보겠습니다.

const getPeopleDetailPage = async (req) => {
  const person = await getPerson(req.params.slug)
  const posts = await getPosts(person)

  return { person, posts }
}


여기에서 사람과 게시물은 모두 범위에 있으므로 중첩할 필요가 없습니다.

Async await는 다른 약속을 함께 결합하는 기능에 적합합니다. 범위 내에서 항목을 유지하는 데 도움이 되므로 )를 잊지 않고 47번 들여쓰기할 필요가 없습니다!

약속보다 나을지도...



나중에 업그레이드



"태그"라는 새 컬렉션이 표시되고 Ryan의 세부 정보 페이지에 태그를 포함하려고 한다고 가정해 보겠습니다.

새 데이터베이스는 다음과 같습니다.

// MongoDB
{
  people: [
    { _id: 1, slug: 'ryan', name: 'Ryan Haskell-Glatz' },
    // ... more people
  ],
  posts: [
    { _id: 12, slug: 'elm-is-neat', title: 'Elm is neat.', author: 1 },
    { _id: 13, slug: 'promises-are-neat', title: 'Promises are neat.', author: 1 },
    { _id: 14, slug: 'saying-neat-is-neat', title: 'Saying neat is neat.', author: 1 },
    // ... more posts
  ],
  tags: [
    { _id: 25, name: 'js', people: [ 1 ] },
    { _id: 26, name: 'elm', people: [ 1, 2 ] },
    { _id: 27, name: 'web', people: [ 1, 5 ] },
    // ... more tags
  ]
}


그리고 새로운getTags 함수:

const getTags = (person) =>
  mongoose.model('tags')
    .find({ people: person })
    .select('name')
    .lean()
    .exec()

Promise.all로 함수를 업데이트하여 멋진 일을 할 수 있습니다.

const getPeopleDetailPage = async (req) => {
  const person = await getPerson(req.params.slug)
  const [ posts, tags ] = await Promise.all([
    getPosts(person),
    getTags(person)
  ])

  return { person, posts, tags }
}

Promise.all를 사용하면 작업을 병렬로 처리하므로 놀라운 성능 및 오류 처리 이점을 얻을 수 있습니다.

오류 처리



이 기능 외에 사용자는 오류 처리 방법을 결정할 수 있습니다.

이것이 ExpressJS가 있는 API 끝점인 경우 다음과 같이 표시될 수 있습니다.

const express = require('express')
const app = express()

app.get('/api/people/:slug', (req, res, next) =>
  getPeopleDetailPage(req)
    .then(data => res.json(data))
    .catch(err => next(err))
)


try-catch 없이 async/await를 사용했음을 주목하세요. 만세!



그게 다야!



즐겁게 읽으셨기를 바라며, 마침내 async await를 사용하게 되어 기쁩니다. 사용의 이점을 공유하고 싶었습니다.

만능은 아니지만 Promise와 잘 어울립니다.

Async await: 60% of the time, it works every time.



좋은 웹페이지 즐겨찾기