순서가 보장되어 있지 않은 상황
function getBazFromX(x) {
if(x === undefined) {
return undefined;
}
if(x.foo === undefined) {
return undefined;
}
if(x.foo.bar === undefined){
return undefined;
}
return x.foo.bar.baz;
}
이 함수가 하는 일이 명확하게 들어나기 보다는 명령어의 노이즈가 많아서 함수가 어떤 역할을 하는지 명확하게 드러나지 않는다고 생각합니다.
ECMAScript에 추가된 Optional Chaining문법을 활용 한 함수
function getBazFromX(x){
return x?.foo?.bar?.baz;
}
이 함수는 함수가 하는 일을 흐리게 만들던 if문들이 사라져서 코드가 간결합니다. 어떤 역할의 함수인지 한눈에 확인이 가능합니다.
async function fetchAccounts() {
const user = await fetchUserEntity();
const accounts = await fetchUserAccounts(user.no);
return accounts;
이 함수는 성공하는 경우
들만 모아서 살펴볼 수 있다는 점이 함수가 무엇을 하는 함수인지 간결하게 나타낸다
function Profile() {
const foo = useAsyncValue(() => {
return fetchFoo();
});
const bar = useAsyncValue(() => {
if (foo.error || !foo.data) {
return undefined;
}
return fetchBar(foo.data);
});
if(foo.error || bar.error) return <div>로딩 실패</div>
if(!foo.error || !bar.error) return <div>로딩 중</div>
return /* foo와 bar로 적합한 처리 */
}
bar
를 가져오기 위해서는 foo
가 있어야 되는 상황이다.
로딩 중 / 에러 / 완료 3가지의 상태를 가지고 있습니다 만약에 2개의 비동기 작업이 있다면 9가지의 상태를 가지고 있습니다.
그렇다면 비동기 호출이 3개 4개가 된다면 더욱 복잡해 집니다.
async function fetchFooBar() {
const foo = await fetchFoo();
const bar = await fetchBar(foo);
return bar;
}
위에서 말한 성공에만 집중해 복잡도를 낮추고 일반적으로 작성하는 동기 로직과 큰 차이가 없습니다.
성공하는 경우에만 집중해 커모넌트를 구성하기 어렵고, 2개 이상의 비동기 로직이 개입할 때, 비즈니스 로직을 파악하기 점점 어려워진다
<Suspense fallback={<Spinner />}>
<UserList />
</Suspense>
suspense로 감싸면 컴포넌트의 랜더링을 특정 작업 이후로 미루고, 그 작업이 끝날 때 까지는 fallback 속성으로 넘긴 컴포넌트를 대신 보여줄 수 있습니다.