JavaScript에서 취소 가능한 비동기 지연 구현
11066 단어 promiseasyncjavascript
fetch()
을 사용하여 검색된 API의 데이터로 일부 상태를 주기적으로 업데이트해야 했습니다. C# 배경에서 이 문제에 접근하는 방식은 다음과 같습니다.private async Task FetchDataContinuouslyAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
await FetchDataAndSetStateAsync(cancellationToken);
// now wait for 15 seconds before trying again
await Task.Delay(15000, cancellationToken);
}
}
당연히 JavaScript에서도 같은 방식으로 문제에 접근했습니다. 그것이 내가 걸림돌을 치는 곳입니다.
Task.Delay()
과 유사한 내장 기능이 없습니다.이것은 내가 문제에 대한 내 자신의 해결책을 생각해 내야 한다는 것을 의미했습니다. 인터넷을 검색하면 사람들이
setTimeout
과 함께 Promise
을 사용하는 많은 결과가 나왔지만 놀랍게도 조기 취소를 지원하는 사람은 거의 없었고 취소에 대한 토큰을 관찰하기보다 취소 기능을 반환하는 경향이 있었습니다. 이미 요청을 취소하기 위해 fetch()
과 함께 AbortController
를 사용하고 있었기 때문에 취소를 위해 해당 컨트롤러를 다시 사용하고 싶었습니다.내가 생각해 낸 것은 다음과 같습니다.
/**
* Return a promise that is resolved after a given delay, or after being cancelled.
*
* @param {number} duration The delay, in milliseconds.
* @param {AbortSignal|null} signal An optional AbortSignal to cancel the delay.
*
* @return {Promise<void>} A promise that is either resolved after the delay, or rejected after the signal is cancelled.
*/
function asyncSleep(duration, signal) {
function isAbortSignal(val) {
return typeof val === 'object' && val.constructor.name === AbortSignal.name;
}
return new Promise(function (resolve, reject) {
let timeoutHandle = null;
function handleAbortEvent() {
if (timeoutHandle !== null) {
clearTimeout(timeoutHandle);
}
if (signal !== null && isAbortSignal(signal)) {
signal.removeEventListener('abort', handleAbortEvent);
}
reject(new DOMException('Sleep aborted', 'AbortError'));
}
if (signal !== null && isAbortSignal(signal)) {
signal.addEventListener('abort', handleAbortEvent);
}
timeoutHandle = setTimeout(function () {
if (signal !== null && isAbortSignal(signal)) {
signal.removeEventListener('abort', handleAbortEvent);
}
resolve();
}, duration);
});
}
이 함수는 첫 번째 매개변수로 밀리초 단위의 지연을 사용하고 두 번째 매개변수로 선택적
AbortSignal
을 사용합니다. 지정된 지연 후 해결되거나 취소가 요청된 경우 Promise<void>
로 거부되는 AbortError
를 반환합니다.React 프로젝트의 맥락에서 이것은
useEffect
후크 내에서 다음과 같이 사용될 수 있습니다.useEffect(() => {
const ac = new AbortController();
async function fetchDataContinuously(abortController) {
while (!abortController.signal.aborted) {
try {
await getData(abortController.signal);
await asyncSleep(refreshInterval, abortController.signal);
} catch (e) {
if (e.name === 'AbortError') {
break;
}
console.error('Error continuously refreshing', e);
}
}
}
fetchDataContinuously(ac).catch(console.error);
return () => {
ac.abort();
};
}, []);
물론 이것은
AbortController
에서 componentWillUnmount
를 단순히 중단함으로써 전통적인 클래스 기반 React 구성 요소와 함께 사용할 수도 있습니다.
Reference
이 문제에 관하여(JavaScript에서 취소 가능한 비동기 지연 구현), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/euantorano/implementing-a-cancellable-asynchronous-delay-in-javascript-2agj텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)