우연히 한 블로그에서 "각 태스크의 실행 순서가 중요한 경우라면 async-await를 사용하자!"
라는 문장을 보게 되었고, 며칠 전 사이드 프로젝트에서 SNS Login 했던 코드가 생각나게 되었다.
코드의 양을 줄일 수 있고 명확하게 작성할 수 있을 거라 판단되어 async-await를 적용하기로 했다.
함수 앞에 async를 붙이고 try-catch를 추가하면서 궁금하기 시작했다.
"async-await에 try-catch는 필수인가?"
try {
setTimeout(() => { throw new Error('error!'); }, 1000);
// 해결 방법
// setTimeout(() => {
// try {
// throw new Error('error!');
// } catch(err) {
// console.log(err);
// }
// }, 1000);
} catch(err) {
console.log(err);
}
const asyncFn = async () => {
console.log('start');
const rj1 = await rejectFn1();
console.log(rj1);
const rj2 = await rejectFn2();
console.log(rj2);
}
const rejectFn1 = () => Promise.reject('rejectFn1 rejected');
const rejectFn2 = () => Promise.reject('rejectFn2 rejected');
asyncFn()
.then(() => {
console.log('next asynFn()');
})
const asyncFn = async () => {
console.log('start');
const rj1 = await rejectFn1();
console.log(rj1);
const rj2 = await rejectFn2();
console.log(rj2);
}
const rejectFn1 = () => Promise.reject('rejectFn1 rejected');
const rejectFn2 = () => Promise.reject('rejectFn2 rejected');
asyncFn()
.then(() => {
console.log('next asynFn()');
})
.catch((e) => {
console.log('asyncFn catch', e);
})
const asyncFn = async () => {
try {
console.log('start');
const rj1 = await rejectFn1();
console.log(rj1);
const rj2 = await rejectFn2();
console.log(rj2);
} catch (err) {
console.log('catch in asyncFn -', err)
}
}
const rejectFn1 = () => Promise.reject('rejectFn1 rejected');
const rejectFn2 = () => Promise.reject('rejectFn2 rejected');
asyncFn()
.then(() => {
console.log('next asynFn()');
})
.catch((e) => {
console.log('asyncFn catch', e);
})
const getError = async () => { throw new Error('error!'); }
const withTryCatch = async () => {
try {
console.log('try-cath 사용한 async');
const result = await getError();
console.log('withTryCatch - 에러 다음 코드 (실행되면 안 됨)');
return result;
} catch (err) {
throw err;
}
}
const withoutTryCatch = async () => {
console.log('try-cath 없는 async');
const result = await getError();
console.log('withoutTryCatch - 에러 다음 코드 (실행되면 안 됨)');
return result;
}
withTryCatch()
.then(res => {
console.log('withTryCatch - 성공', res);
}).catch(err => {
console.log('withTryCatch - 실패', err.message);
});
withoutTryCatch()
.then(res => {
console.log('withoutTryCatch - 성공', res);
})
.catch(err => {
console.log('withoutTryCatch - 실패', err.message);
})
const asyncFn = async () => {
console.log('start');
try {
const rj1 = await rejectFn1();
console.log(rj1);
} catch (err) {
console.log(`catch in rejectFn1 - ${err}`);
}
try {
const rj2 = await rejectFn2();
console.log(rj2);
} catch (err) {
console.log(`catch in rejectFn2 - ${err}`);
}
}
const rejectFn1 = () => Promise.reject('rejectFn1 rejected');
const rejectFn2 = () => Promise.reject('rejectFn2 rejected');
asyncFn()
.then(() => {
console.log('next asynFn()');
})
.catch((e) => {
console.log('asyncFn catch', e);
})
const asyncFn = async () => {
console.log('start');
const rj1 = await rejectFn1().catch(err => { return `catch in rejectFn1 - ${err}`; });
console.log(rj1);
const rj2 = await rejectFn2().catch(err => { return `catch in rejectFn2 - ${err}`; });
console.log(rj2);
}
const rejectFn1 = () => Promise.reject('rejectFn1 rejected');
const rejectFn2 = () => Promise.reject('rejectFn2 rejected');
asyncFn()
.then(() => {
console.log('next asynFn()');
})
.catch((e) => {
console.log('asyncFn catch', e);
})
const anotherThing = async (some) => {
if (some.cnt === 0) {
return Promise.reject({
message: '서비스 로직 에러',
status: 403,
})
}
return Promise.resolve({ message: '성공' })
}
// 컨트롤러 로직
app.get('/foo', async (req, res, next) => {
try {
// 비동기 결과가 reject 라면 catch 문으로 점프
const some = await something();
// 비동기 결과가 reject 라면 catch 문으로 점프
const another = await anotherThing(some);
// 앞쪽에서 아무런 문제도 없어야 성공 결과가 응답됨
res.json(another);
} catch (err) {
// throw err를 하지 않음 (상위 컨텍스트로 에러를 전파하지 않음)
// 클라이언트로 에러를 응답
res.status(err.status || 500).json({
message: err.message || 'unknown error'
})
}
});
참고
https://velog.io/@vraimentres/async-%ED%95%A8%EC%88%98%EC%99%80-try-catch
https://merrily-code.tistory.com/214
https://itnext.io/async-await-without-try-catch-in-javascript-6dcdf705f8b1
https://itnext.io/error-handling-with-async-await-in-js-26c3f20bc06a
https://stackoverflow.com/questions/40884153/try-catch-blocks-with-async-await
https://blog.grossman.io/how-to-write-async-await-without-try-catch-blocks-in-javascript/
https://softwareengineering.stackexchange.com/questions/144326/try-catch-in-javascript-isnt-it-a-good-practice
https://programmingsummaries.tistory.com/375