node JS 톺아보기(2)

비구조화 할당(destructuring)


리액트를 공부했을 때 항상 상단에 import React, { Component } from 'react'; 를 썼었는데, 저 { Component } 의 의미를 몰랐었다.

근데 이게 비구조화 할당이었다! 비구조화 할당이 뭔지 정리해보자.

const object = {
    status : {
        name: 'node',
        count: 4,
    },
    getCount(){
        this.status.count--;
        return this.status.count;
    }
}

const {status, getCount} = object //object 객체의 각 속성이 status와 getCount에 할당된다.  반드시 객체의 속성 값과 변수 이름이 같아야한다.

console.log(status.name) //node

node에서도 의미를 모르고 썼던 const { Router } = require('express')require('express')로 가져온 객체에서 Router의 속성을 변수로 꺼내온다는 의미이다.

위 예제에서 조심해야할 부분이 있다.

const object = {
    status : {
        name: 'node',
        count: 4,
    },
    getCount(){
        this.status.count--;
        return this.status.count;
    }
}

const {status, getCount} = object

getCount() //결과 : 객체 this를 못찾아서 아무일도 일어나지 않는다. 즉 count 값이 바뀌지 않는다.

getCount.call(object) //이렇게 객체를 연결해줘야 count가 3이 된다.

비구조화 할당은 배열도 된다!


const array = [1, {}, true, 'node']
const {number, obj, bool, name} = array; //배열의 순서에 맞게 변수로 꺼내올 수 있다...왕신기

콜백 지옥


Users.findOne('sy', (err,user)=>{
    if(err){
        console.error(err)
    }
    console.log(user)
    Users.update('ha',(err,updatedUser)=>{
        if(err){
            console.error(err)
        }
        console.log(updatedUser)
        Users.remove('ho',(err,removedUser) =>{
            if(err){
                console.error(err)
            }
            console.log(removedUser)
            Users.callbackHell('hell',(err,hell)=>{
                .....//콜백지옥
            })
        })
    })
})

위 코드를 이해할 수 없다..like 사중포문과 같은 가독성..

그래서 나온게 Promise!

Promise


Promise는 결과값을 가지고 있지만 .then()이나 .catch()를 붙이기 전까지 반환하지 않는 것!

(결과를 lazy하게 뒤로 미룬다는 점에서 함수형 프로그래밍과 비슷하다고 개인적으로 생각한다…)

위의 코드를 대충 이렇게 바꿀 수 있다.

const Users = {
    findOne(){
        return new Promise((resolve,reject) => {
            if(사용자를 찾았으면){
                resolve(사용자) //인수로 넘긴 값(=사용자)이 then의 파라미터로 들어간다.
            }else{
                reject(못찾음)//인수로 넘긴 값이 catch의 파라미터로 들어간다.
            }
        })
    },
    update(){
        return new Promise((resolve,reject) => {
            if(업데이트 성공했으면){
                resolve(사용자)
            }else{
                reject(실패)
            }
        })
    },
    remove(){
        return new Promise(...)
    },
}

Users.findOne('sy')
    .then((user)=>{
        console.log(user)
        return Users.update('ha')//promise리턴
    })
    .then((updatedUser)=>{
        console.log(updatedUser)
        return Users.remove('ho')
    })
    .then((removedUser)=>{
        console.log(removedUser)
    })
    .catch((err)=>{
        console.error(err)
    })

중요한 건 Promise의 왼쪽 파라미터 함수(예제에서는 resolve)의 인자로 넘긴 값이 .then()의 파라미터로 들어가고, Promise의 오른쪽 파라미터 함수(예제에서는 reject)의 인자로 넘긴 값이 .catch()의 파라미터로 들어간다는 것이다.

.then()에 리턴값 Promise가 있으면 다음 .then()으로 넘어간다.


async / await


어쨌든 Promise를 써도 아래 코드는 비동기적으로 실행된다.

Users.findOne('sy')
    .then((user)=>{
        console.log(user)
        return Users.update('ha')//promise리턴
    })
    .then((updatedUser)=>{
        console.log(updatedUser)
        return Users.remove('ho')
    })
    .then((removedUser)=>{
        console.log(removedUser)
    })
    .catch((err)=>{
        console.error(err)
    })

console.log('콘솔에 내가 먼저 찍힌다.')

그럼 코드 순서와 실행 순서가 같아지는 동기식으로 어떻게 바꿀까?

async / await 키워드를 사용한다!

async func() = {
    try{
        const user = await Users.findUser('sy') //Promise의 resolve() 또는 reject()의 파라미터로 넘기는 값이 user로 리턴된다.
        console.log(user)

        const updated = await Users.update('ha')
        console.log(updated)
        
        const removed = await Users.remove('ho')
        console.log(removed)

        console.log('난 맨 마지막에 찍힌다.')
    } catch(err){
        console.error(err)
    }
    
}

func()

위의 코드처럼 함수 앞에는 async , Promise에는 await을 붙여주면 코드를 작성한 순서대로 기다렸다가 다음 코드가 실행된다. = 동기식


다시 찾아볼 부분

.bind() 의 뜻



Comments