Nailer's blog

Node-Promise&async/await

March 20th, 2019

nodejs

Promise


A promise is an object that may produce a single value some time in the future

promise๋Š” javascript ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ์— ์‚ฌ์šฉ๋˜๋Š” ๊ฐ์ฒด์ด๋‹ค.

promise ์‹ค์Šต์„ ์œ„ํ•ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.

const add = (a, b) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(a+b)
    }, 2000)
  })
}

add(1, 2)
  .then((sum) => {
    console.log(sum)

    add(sum, 5)
      .then((sum2)=> {
        console.log(sum2)
      })
      .catch(error1 => {
        console.log(error1)
      }) 

  })
  .catch(error => {
    console.log(error)
  })

Promise chaining์„ ํ†ตํ•ด ๋” ๊ฐ„๊ฒฐํ•œ ์ฝ”๋“œ๋ฅผ ๋ณผ ์ˆ˜์žˆ๋‹ค.

add(1, 1)
  .then(sum => {
    console.log(sum)
    return add(sum, 4)
  })
  .then(sum2 => {
    console.log(sum2)
  })
  .catch(error => {
    console.log(error)
  })

Promise Chaining์„ ์ด์šฉํ•œ update

require('../src/db/mongoose')
const User = require('../src/models/user')

User.findByIdAndUpdate('5c7b8e0ea401383fea0d8084', { age: 12 })
  .then(user => {
    console.log(user)
    return User.countDocuments({ age: 12 })
  })
  .then(result => {
    console.log(result)
  })
  .catch(error => {
    console.log(error)
  })

์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•˜์ง€๋งŒ,

DeprecationWarning: collection.findAndModify is deprecated. Use findOneAndUpdate, findOneAndReplace or findOneAndDelete instead.

์ด๋Ÿฌํ•œ ๊ฒฝ๊ณ ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”๋ฐ

mongoose.connect('mongodb://127.0.0.1:27017/task-manager', {
  auth: {
    "authSource": "admin"
  },
  user: 'user',
  password: 'passoword',
  useNewUrlParser: true,
  useFindAndModify: false,
})

์œ„์™€ ๊ฐ™์ด useFindAndModify ์„ค์ •์„ false๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ๋œ๋‹ค.

๋˜ํ•œ, findByIdAndUpdate() method๋Š” update ์ด์ „์˜ ์›๋ณธ document๋ฅผ return ํ•œ๋‹ค.

task ๋กœ ์‹ค์Šตํ•ด๋ณธ promise chaining

require('../src/db/mongoose')
const Task = require('../src/models/task')

Task.findByIdAndDelete('5c7b9c3a6e27c7bca66049ac')
  .then(task => {
    console.log(task + ' is deleted')
    return Task.countDocuments({ completed: false })
  })
  .then(numOfTasks => {
    console.log(numOfTasks + ' tasks are not completed')
  })
  .catch(error => {
    console.log(error)
  })

๊ฒฐ๊ณผ๊ฐ’

{ completed: true,
  _id: 5c7b9c3a6e27c7bca66049ac,
  description: '๋ธ”๋กœ๊ทธํฌ์ŠคํŒ…ํ•˜๊ธฐ' } is deleted
11 tasks are not completed

Async / Await


test 1

const doWork = () => {
  
}

console.log(doWork())

// <result>
// undefined

test 2

const doWork = async () => {
  
}

console.log(doWork())

// <result>
// Promise { undefined }

Async์— ์˜ํ•ด Promise ๊ฐ์ฒด๊ฐ€ ๋ฐ˜ํ™˜๋˜์—ˆ๋‹ค.

test 3

const doWork = async () => {
  return 'Nailer'
}

console.log(doWork())

// <result>
// Promise { 'Nailer' }

๋”ฐ๋ผ์„œ ํ•ญ์ƒ async๋Š” Promise ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

test 4

const doWork = async () => {
  return 'Nailer'
}


doWork()
  .then(result => {
    console.log('result', result)
  })
  .catch(error => {
    console.log('error', error)
  })

// <result>
// result Nailer

Promise ๊ฐ์ฒด์ด๋ฏ€๋กœ ์œ„์™€ ๊ฐ™์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

test 5

const add = (a, b) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(a + b)
    }, 2000)
  })
}

const doWork = async () => {
  const sum = await add(1, 99)
  const sum2 = await add(sum, 50)
  const sum3 = await add(sum2, 3)
  return sum3
}


doWork()
  .then(result => {
    console.log('result', result)
  })
  .catch(error => {
    console.log('error', error)
  })

test 6

const add = (a, b) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if(a < 0 || b < 0) {
        return reject('numbers must be non-negative')
      }
      resolve(a + b)
    }, 2000)
  })
}

const doWork = async () => {
  const sum = await add(1, 99)
  const sum2 = await add(sum, 50)
  const sum3 = await add(sum2, -3)
  return sum3
}


doWork()
  .then(result => {
    console.log('result', result)
  })
  .catch(error => {
    console.log('error', error)
  })

// <result> 6์ดˆ ๋’ค...
// error numbers must be non-negative

const doWork = async () => {
  const sum = await add(-1, 99)
  const sum2 = await add(sum, 50)
  const sum3 = await add(sum2, -3)
  return sum3
}

// <result> 2์ดˆ ๋’ค...
// error numbers must be non-negative

์ฒซ ๋ฒˆ์งธ await์—์„œ error shooting์„ ํ•ด์„œ ๋’ค์˜ await๋“ค์€ ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค.

๋ฐฐ์šด Promise์™€ async/await ์ฝ”๋“œ๋ฅผ ํ˜ผ์šฉํ•  ๊ฒฝ์šฐ

require('../src/db/mongoose')
const User = require('../src/models/user')

User.findByIdAndUpdate('5c7b8e0ea401383fea0d8084', { age: 111 }) 
  .then(user => {                                                
    console.log(user)
    return User.countDocuments({ age: 111 })
  })
  .then(result => {
    console.log(result, 'PromiseChaining')
  })
  .catch(error => {
    console.log(error)
  })

const updateAgeAndCount = async (id, age) => {
  const user = await User.findByIdAndUpdate(id, { age: age })
  const count = await User.countDocuments({age: age})

  return count
}

updateAgeAndCount('5c7b8e0ea401383fea0d8084', 3)
  .then(count => {
    console.log(count, 'async/await')
  })
  .catch(error => {
    console.log(error)
  })

์ด์™€ ๊ฐ™์ด ๊ฐœ๋ณ„์ ์œผ๋กœ ํ•˜๋‚˜์˜ document์— ๋Œ€ํ•œ ์ˆ˜์ •์„ ๊ฐ€ํ–ˆ์„ ๋•Œ

image-20190322223554675

updateAgeAndCount๊ฐ€ ๋จผ์ €

User.findByIdAndUpdate('5c7b8e0ea401383fea0d8084', { age: 111 }) //The operation returns the original document before the update:
  .then(user => {                                                
    console.log(user)
    return User.countDocuments({ age: 111 })
  })
  .then(result => {
    console.log(result, 'PromiseChaining')
    return updateAgeAndCount('5c7b8e0ea401383fea0d8084', 3)
  })
  .then(count => {
    console.log(count, 'async/await')
  })
  .catch(error => {
    console.log(error)
  })

์ด์™€ ๊ฐ™์ด Chaining์„ ํ™œ์šฉํ•œ๋‹ค.

Promise์™€ async/await๋ฅผ ์‚ฌ์šฉํ•ด์™”์ง€๋งŒ, ๋ช…ํ™•ํ•˜๊ฒŒ ์•Œ ์ˆ˜ ์žˆ๋Š” ๊ธฐํšŒ๋ฅผ ๊ฐ€์กŒ๋‹ค.

Created by SeongHeum CHOI, 2020