Nodejs - callback 콜백함수 , promise, async/await

dev_swan·2022년 2월 7일
0

Nodejs

목록 보기
18/20
post-thumbnail

callback 콜백함수 // 동기 비동기

  • 동기와 비동기를 알아보기위해 이런식으로 코드를 짜고 실행을 하게되면 어떤식으로 출력될까 확인해보자

  • 출력 결과

  • 출력된 순서로 코드를 확인해보면
  1. 1 = console.log(1) // 동기

  2. 3 = console.log(3) // 동기

  3. Syschronous callback = printImmediately(print){print();} printImmediately(()=>{console.log('hello')})
    // (동기적으로 실행하는 callback)

  4. 2 = setTimeout(()=>{console.log('2')},0) // 비동기

  5. Asynchronous callback = printWithDelay(print, timeout)
    {setTimeout(print,timeout)}printWithDelay(()=>{console.log('Asynchronous callback')},2000)

    // (비동기적으로 실행하는 callback)

위처럼 출력된 것을 보아 동기들이 먼저 출력되고 그 후에 setTimeout이 들어간 비동기들이 출력되는것을 확인할 수 있다.
또 callback 중에서도 동기적으로 실행하는 Syschronous callback과 비동기적으로 실행하는 Asynchronous callback이 있음을 알 수 있다.

콜백지옥 callback hell

자바스크립트는 비동기 프로그램이라는 특성상 이벤트에 따라 받는 콜백이 복잡해지면 내부에서 지속적으로 콜백을 사용하게 되므로 코드 읽기가 아주 어려워지는 상황이 발생하게 된다. 이러한 상황을 콜백헬(Callback Hell) 이라고 한다.

출처 - https://acaroom.net/ko/blog/youngdeok/callback-hell%EC%9D%84-%EC%A4%84%EC%9D%B4%EA%B8%B0-%EC%9C%84%ED%95%9C-nodejs%EC%9D%98-%EB%B0%A9%EB%B2%95

promise

  • 정의
    Javascript안에 내장되어 있는 비동기를 간편하게 처리할 수 있는 object

  • 역할
    callback을 위처럼 유용하게 쓰일때도 있지만 이렇게 callback을 계속해서 callback 안에 callback 함수를 부르고 부르다 보면 콜백지옥이 될 수 있기에 이를 보완하기 위해서 사용한다.

  • 사용법 ( Promise의 3가지 상태(states) )

Pending(대기) : 비동기 처리 로직이 아직 완료되지 않은 상태

new Promise((resolve,reject)=>{
  // 빈값
});

Promise 메소드를 호출할 때 콜백함수를 선언할 수 있고 인자값은 resolve(성공시 반환)와 reject(실패시 반환)입니다.

Fulfilled(이행) : 비동기 처리가 완료되어 프로미스가 결과 값을 반환해준 상태

function prcatice(){
    return new Promise((resolve,reject)=>{
		let data = 100;
		resolve(data);
    });
}

prcatice().then((resolvedata)=>{
	console.log(resolvedata)
})

콜백함수 resolve를 사용하여 이행상태로 만들고 .then을 사용하여 값을 전달받을 수 있습니다.

Rejected(실패) : 비동기 처리가 실패하거나 오류가 발생한 상태

function prcatice(){
    return new Promise(function(resolve,reject){
        reject(new Error("OO 에러가 발생하였습니다"))
    })
}

prcatice().then().catch(function(rejecterr){
	console.log(rejecterr)
})

에러가 발생되면 catch로 무슨 에러가 발생했는지 확인할 수 있습니다.

  • 사용예시 (Promise를 사용X)
const time = ()=>(parseInt(Math.random()*10)+1)*1000

const 아반떼 = cb => {
    setTimeout(()=>{
        console.log('아반떼 End')
        cb()
    }
    ,time())
    console.log('아반떼 Go')
}
const 소나타 = cb => {
    setTimeout(()=>{
        console.log('소나타 End')
        cb()
    },time())
    console.log('소나타 Go')
}
const 제네시스 = cb => {
    setTimeout(()=>{
        console.log('제네시스 End')
        cb()
    }
    ,time())
    console.log('제네시스 Go')
}

console.log("경기시작")
아반떼(()=>{
    소나타(()=>{
        제네시스(()=>{
            console.log("경기 종료")
        })
    })
})
  • 결과

  • 사용예시 (Promise를 사용O)
const time = ()=>(parseInt(Math.random()*10)+1)*1000

const 아반떼 = () => {
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve("아반떼 End")
        },time())
        console.log('아반떼 Go')
    })
}

const 소나타 = () => {
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve("소나타 End")
        },time())
        console.log('소나타 Go')
    })
}

const 제네시스 = () => {
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve("제네시스 End")
        },time())
        console.log('제네시스 Go')
    })
}

console.log('경기 시작')
아반떼()
.then(data=>{
    console.log(data)
    return 소나타()
})
.then(data=>{
    console.log(data)
    return 제네시스()
})
.then(data=>{
    console.log(data)
    console.log('경기 종료')
})
  • 결과

코드가 많아 질수록 callback을 많이 사용하여 코드가 > 이런식으로 밀리게 되어 코드를 읽기 어려워지지만 Promise 객체를 사용하여 이를 방지하였다. (코드가 길어진다면 더 효과가 좋을거같다.)

async/await

  • 정의
    Javascript의 비동기를 처리하는 비교적 최근에 나온 문법

  • 역할
    Promise를 조금 더 간결하고 간편하고 동기적으로 실행되는것처럼 보이게 해준다.

  • 사용예시

const time = ()=>(parseInt(Math.random()*10)+1)*1000

const 아반떼 = () => {
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve("아반떼 End")
        },time())
        console.log('아반떼 Go')
    })
}

const 소나타 = () => {
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve("소나타 End")
        },time())
        console.log('소나타 Go')
    })
}

const 제네시스 = () => {
    return new Promise((resolve,reject)=>{
        setTimeout(()=>{
            resolve("제네시스 End")
        },time())
        console.log('제네시스 Go')
    })
}

async function init(){
    console.log('경기 시작')
    let a = await 아반떼()
    console.log(a)
    let b = await 소나타()
    console.log(b)
    let c = await 제네시스()
    console.log(c)
    console.log('경기 종료')
}

init()

함수 앞에 async를 사용하여 자동으로 Promise로 바꿔주고 await은 async가 붙은 함수 안에서만 사용할 수 있고 promise객체의 딜레이가 끝날때까지 기다려준 후 실행한다.

  • 결과

promise를 사용했을때 .then으로 값을 가져오는것 보다 보기 편한것 같다.

0개의 댓글