이번 시간에는 eslint 룰 중 하나인, require-atomic-updates에 대해 알아보았다!
1. eslint룰, require-atomic-updates
1) 이 규칙은?
await
가 레이스 컨디션을 유발할 경우,await
사용을 금지하는 규칙이다.
2) await가 레이스 컨디션을 유발하는 경우
- 아래 예시는
person
의age
데이터를 가져와,age
의 총합을 구하는 로직이다.
const PEOPLE = [{ id: 1, age: 12 }, { id: 2, age: 22 }];
let totalAge = 0;
// await를 사용해 age의 총합을 구하는 함수
async function addAge(id) {
totalAge += await getAge(id); // 주요하게 볼 부분
}
// id에 해당하는 age를 리턴하는 함수
async function getAge(id) {
const randomTime = Math.random() * 1000;
await waiting(randomTime);
return PEOPLE.find((person) => person.id === id).age;
}
// 비동기 역할을 하는 함수
async function waiting(time) {
setTimeout(() => {
Promise.resolve('End waiting');
}, time);
}
// age총합 구하는 로직
await Promise.all([addAge(1), addAge(2)]); // 병렬로 실행
console.log('total age:', totalAge);
😯
totalAge
의 결과는 무엇일까? 신기하게도 34가 아닌 22가 나온다! 이유는 무엇일까?
- 함수 실행 순서와 함께 이유를 알아보자!
async function addAge(id) {
totalAge += await getAge(id); // 버그 발생 지점!
}
await Promise.all([addAge(1), addAge(2)]); // 함수 실행
console.log('total age:', totalAge);
함수 실행 순서 | 설명 |
---|---|
addAge(1) 실행 | getAge(1) 에서 totalAge 의 초기값을 읽는다. (이때 초기값은 0) |
getAge(1) 에서 Promise가 완료될 때까지 기다린다. |
|
addAge(2) 실행 | Promise.all 은 병렬 실행하므로,getAge(1) 의 Promise 결과를 기다리는 동안 getAge(2) 가 실행한다. |
getAge(1) 이 완료되지 않은 상태에서 getAge(2) 가 실행되므로,totalAge 의 초기값이 0인 상태에서 변수를 업데이트하여 결과값이 22가 나온다. |
그렇다면 어떻게 하면 레이스컨디션을 피할 수 있을까? 2가지 방법을 살펴보자!
3) await의 레이스컨디션을 피하는 방법
(1) await가 끝나면 데이터 업데이트하기
getAge(id)
의Promise
가 끝난 뒤age
값을 받아,totalAge
의 값을 업데이트하는 방법이다.
async function addAge(id) {
const age = await getAge(id); // 변경
totalAge += age;
}
(2) 변수 참조하지 않기
await
로 인해 레이스컨디션이 발생한 이유는, 참조 변수값을 업데이트할 때 이전의 Promise가 끝나기 전에 다른 Promise를 실행했기 때문이다.- 그러므로 아래와 같이, 지역 변수를 선언하여 값을 계산해주면 레이스컨디션을 피할 수 있다!
Promise.all([getAge(1), getAge(2)]).then(ages => {
const totalAge = ages.reduce((acc, age) => acc + age, 0);
console.log(totalAge);
});
반응형
'개발 기술 > 사소하지만 놓치기 쉬운 개발 지식' 카테고리의 다른 글
[CSS] font-display, 글꼴 렌더링 방식을 변경하는 방법 (0) | 2022.12.22 |
---|---|
[CSS] 애니메이션 동작을 컨트롤하는, prefers-reduced-motion (0) | 2022.12.11 |
[JS/Eslint] 반복문에서 await를 쓰지말자(no-await-in-loop) (0) | 2022.08.27 |
[JS] 객체의 얕은 복사, 깊은 복사(feat. StructuredClone) (0) | 2022.08.14 |
[SASS/SCSS] hex, rgb 컬러에 투명도 주는 방법 (0) | 2022.07.23 |
댓글