promise와 async/await비교

2018-11-23

싱글스레드인 자바스크립트는 비동기처리를 위해 콜백을 사용한다.
그러나 비동기를 중첩시켜서 사용을 하면 에러,예외 처리가 어려워져 중첩도로 인해 복잡성이 증가한다.
이러한 단점을 해결하기 위해 나온게 promise이다.


promise


    - ES6 문법
    - resolve 결과가 then, reject가 catch문으로 가게 됨

async/await


    - ES8 문법
    - 코드의 간결성
    - 동기식으로 처리
    - await뒤에는 항상 프로미스를 반환해야한다.


차이점 정리


1. 에러처리

promise문에서 getJSON을 통해서 데이터를 받아오는 부분과 JSON.parse하는 부분에서 catch문을 사용해서 에러를 잡아야한다.
반면에 async/await 구문에서는 try, catch에서 모든 에러를 다 한번에 잡을 수 있다. 코드가 훨씬 깔끔해질 수 있다.
그러나 실무에서 에러가 발생할때 정확하게 어느 구문에서 발생했는지 알 수 없다.

1
2
3
4
5
6
7
8
9
10
11
12
makerequest = () => {
try {
this.getJSON('a')
.then(result =>{
const data = JSON.parse(result);
}).catch((err) => {
console.log(1, err)
})
} catch(err) {
console.log(2, err)
}
}
1
2
3
4
5
6
7
8

makerequest = async() => {
try {
JSON.parse(await this.getJSON('a'))
} catch (err) {
console.log("Err", err)
}
}

2. 중간값 처리

예를 들어서 사용자의 정보를 받아온 다음 그 정보를 바탕으로 새로운 api를 호출해야하는 경우가 있다.
이 경우 async/await를 사용하면 좀 더 편하게 코드를 짤 수 있다. 사실 이부분이 async/await를 사용하는 가장 큰 이유라고 생각한다.

1
2
3
4
5
6
7
8
9
10
makeRequest = () => {
return this.getJSON()
.then(data => {
return this.makeAnotherRequest(data)
.then(moreData => {
console.log(moreData)
return moreData
});
})
}
1
2
3
4
5
makeRequest = async() => {
const data = await this.getJSON()
const moreData = await this.makeAnotherRequest(data)
console.log(moreData)
}

3. 디버깅

promise는 then블록 내에 디버깅을 찍으면 동기적으로 이동하기 때문에 다음 then으로 이동하지 않는다.
반면 async/await는 바로 다음 await로 이동을 하기 때문에 디버깅하는데 편리하다.

async/await에서 동시에 비동기적으로 값을 가져와야할 때?

이때는 Promise.all()을 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const job = (x) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("x", x)
resolve(x);
}, x * 100);
})
}

timeStamp = async() => {
try {
for (const result of await Promise.all([job(3), job(6), job(9)])) {
console.log(result) //총 걸리는 시간은?? 15초이다!
}
} catch(err) {
console.log(err)
}
}

그러나 ES9에 도입된 for await가 이를 대체해준다.
for await는 for of문에서 처리가능하며 반복적인 비동기 작업을 쉽게 처리해준다.

1
2
3
4
5
6
7
8
9
10
11
timeStamp = async() => {
const promises = [3, 6, 9].map((timer) => (
new Promise((res, req) => { // 총 걸리는 시간은 15초!
setTimeout(() => res(timer), timer * 1000);
})
))

for await (const result of promises) {
console.log(result);
}
}

결론

promise를 대체해서 어떤 경우에서든지 async/await를 사용하는 것을 좋지 않다. 새로운 문법들이 계속 등장하는데 꼭 좋은 것만은 아니라고 한다.
적재적소로 필요할 때 사용하는게 제일 좋다. 본인한테 맞고 잘 사용할 수 있는게 좋다.
새로운 것들이 등장하는 것은 단지 이용을 편리하게 해주는것이므로…