React 비동기 작업 중복 실행 방지

shleecloud·2022년 5월 22일
2
post-thumbnail
post-custom-banner

2024년 기준 업데이트 됐습니다.
https://shlee.cloud/blog/tech/react-debounce-throttle

들어가며

React 환경에서 회원 가입 버튼 같이 비동기 작업으로 결과를 봐야되는 기능을 구현할 때가 있다. 그 버튼을 짧은 시간동안 연타하면 어떻게 될까? 특별한 처리를 하지 않으면 여러번 실행 될 것이다. 중복 실행을 막고 싶을 때 취한 조치에 대해서 기록을 남기고자 한다.

Lodash debounce, throttle

Lodash에서 제공하는 debounce와 throttle 기능을 활용한다.
특정 시간내에 발생하는 작업을 억제할 수 있다. 클릭을 1초동안 3번 클릭할 때 이 함수들을 활용해서 1번만 보내게 만들 수 있다.

단점도 있다. 특정 시간을 기준으로 잡기 때문에 비동기 작업이 예상 시간보다 길어지면 2번 실행될 수 있다. 또한 확장성도 떨어진다. 다른 동작을 막지 못하고 작업 상태를 알 수 없다. 주로 작업 상태를 따로 추적할 필요가 없을 때 유용하다.

아이디 중복을 실시간으로 확인하는 기능처럼 단기간으로 여러 작업을 막을 때 유용하다. client 상에서 scroll 위치나 마우스 위치를 받아드릴 때도 유용하다.

https://css-tricks.com/debouncing-throttling-explained-examples/

debounce

debounce 인자값 func 함수가 호출된 이후 wait 초 만큼 추가로 들어온 작업을 무시한다.

시간 내에 중복 입력이 된 경우 시간 초가 다시 갱신된다.

_.debounce(func, [wait=0], [options={}])

// ------------
func (Function): The function to debounce.
[wait=0] (number): The number of milliseconds to delay.
[options={}] (Object): The options object.
[options.leading=false] (boolean): Specify invoking on the leading edge of the timeout.
[options.maxWait] (number): The maximum time func is allowed to be delayed before it's invoked.
[options.trailing=true] (boolean): Specify invoking on the trailing edge of the timeout.

throttle

wait 초 시간동안 한 번만 throttle 인자값 func 함수를 호출한다.

시간 내에 중복 입력이 된 경우 시간 초가 다시 갱신되지 않는다.

_.throttle(func, [wait=0], [options={}])

// ------------
func (Function): The function to throttle.
[wait=0] (number): The number of milliseconds to throttle invocations to.
[options={}] (Object): The options object.
[options.leading=true] (boolean): Specify invoking on the leading edge of the timeout.
[options.trailing=true] (boolean): Specify invoking on the trailing edge of the timeout.

Hook Flag

비동기 작업시 Promise 상태로 빠지는 것을 활용한다.
여기서 asyncTask 작업은 반드시 promise 상태로 빠져야한다. 그래야 작업이 완료될 때까지 기다리고 Flag를 변경한다. 전달받은 state 값이 변하는 것을 활용해서 다른 동작들도 차단하거나 Loading 모달을 띄울 수도 있다.

async function asyncRedundantPrevent(state, setState, asyncTask) {
    // 중복 실행 차단
    if (state === true) return;

		// Flag 변경
    setState(true);
		// 실행 완료까지 대기
    await asyncTask();
		// Flag 변경
    setState(false);
}
profile
블로그 옮겼습니다. https://shlee.cloud
post-custom-banner

0개의 댓글