본문 바로가기

FrontEnd

XState 상태 기계로 SWR 구현하기

반응형

원문 보러가기

 

SWR-Style Fetching with XState State Machines

Using state machines to intelligently refresh your data

imfeld.dev

 

SWR이 무엇이고 왜 유용한가요?


 
Stale-while-revalidate(SWR)는 캐시된 데이터가 가능한 한 빨리 사용자에게 표시되도록 하는 데이터 가져오기(fetch) 전략입니다.
또한 캐시된 데이터가 오래된 경우 최신 데이터를 가져오도록 어레인지 합니다.
HTTP 캐시에서 주로 볼 수 있는 전략입니다.
react-query 및 SWR React 라이브러리는 이러한 전략을 프론트 엔드에서 구현하기 쉽게 만들었습니다.
 

최신 데이터 보여주기


 
최신 웹 애플리케이션은 사용자에게 표시할 데이터를 가져오는 데 많은 시간을 소비합니다.
그러나 한 번 가져온 데이터는 그 사이에 변경되었더라도 자동으로 업데이트되지 않습니다.
이것은 항상 중요하지는 않지만 사용자 경험에 중요할 수 있습니다.
애플리케이션의 다양한 위치에서 실행할 수 있는 보고서 목록이 있는 데이터 분석 애플리케이션을 상상해 보십시오.
우리가 응용 프로그램을 사용 중이고 다른 팀원이 보고서를 추가하거나 제거하는 경우,
해당 변경 사항은 탭을 다시 로드할 필요 없이 다른 모든 사람에게 반영되어야 합니다.
이에 대한 일부 솔루션은 웹 소켓, 서버 전송 이벤트(websockets, server-sent events) 또는 기타 기술을 사용하여 실시간으로 서버에서 브라우저로 변경 사항을 푸시합니다.
그러나 이러한 솔루션은 응용 프로그램에 상당한 복잡성과 확장 문제를 추가할 수 있으며 대부분의 경우 이점이 거의 없습니다.
SWR은 훨씬 간단한 전략을 취합니다.
 
우리의 상태 머신은 주기적으로 새 데이터를 가져옵니다.
 
일부 다른 SWR 구현은 데이터에 대한 실제 요청을 기다린 다음 업데이트된 데이터를 가져올 때와 캐시로 이동할 때를 결정하는 프록시 역할을 합니다.
이 두 가지 스타일의 SWR 가져오기 중에서 선택하는 것은 응용 프로그램의 특성과 각 데이터의 특정 부분,
가져온 데이터를 사용하는 코드 타입에 따라 다릅니다. 저는 보통 Svelte 스토어를 이용합니다.
무언가가 매장의 데이터를 수신하고 있을 때 이를 쉽게 알 수 있으므로 자동 주기적 새로 고침이 가장 적합합니다.

초기 로드 시 더 나은 동작


처음으로 데이터를 로드하는 것은 작지만 여전히 중요한 과제입니다.

일부 사이트는 서버 사이드 렌더링(SSR)을 사용하여 첫 페이지를 서버에서 통합하여 대기 시간을 줄입니다.

 

그러나 이것이 항상 훌륭한 해결책은 아닙니다.

로드되는 페이지의 초기 데이터는 빌드하는 데 시간이 걸리거나 사용 중인 웹 프레임워크가 SSR을 지원하지 않을 수 있습니다.

 

따라서 사용자가 새 페이지로 전환할 때 세 가지 옵션이 있습니다.
  • 데이터가 로드되는 동안 아무 작업도 수행하지 않고(또는 로드 표시기를 표시) 데이터가 도착하면 페이지를 전환합니다.
  • 페이지를 즉시 전환하되 데이터를 기다리는 동안 로딩 표시기를 표시합니다.
  • 페이지에서 마지막으로 보여준 것을 저장하고, 새로운 데이터가 도착하기를 기다리는 동안 로컬 캐시에서 로드합니다.
SWR은 이 세 번째 접근 방식을 사용합니다.
Twitter iOS 앱은 잘 알려진 예입니다.
이전에 방문한 페이지로 전환하면 이전에 보고 있던 내용이 표시된 뒤 배경에서 새 트윗을 가져옵니다.
로드되면 상단에 볼 새 트윗이 있다는 알림이 표시됩니다.
 


SWR의 동작


SWR 기술은 이 두 가지 데이터 가져오기 동작을 결합하여 사용자에게 좋은 경험을 제공합니다. 다음과 같은 일련의 이벤트를 따릅니다.
  • 로컬에 캐시된 데이터가 있는 경우 사용자가 즉시 유용한 것을 볼 수 있도록 먼저 해당 데이터를 반환합니다.
  • 로컬로 캐시된 데이터를 가져온 후 충분한 시간이 지나면 "stale"이라고 부르고 데이터를 다시 가져옵니다.
  • 주기적으로 SWR 프로세스가 활성화되어 있는 한 데이터가 오래되면 다시 가져옵니다.
대부분의 SWR 라이브러리는 브라우저 창에 초점이 없거나 인터넷 연결이 오프라인인 경우, 데이터를 가져오지 않습니다.
이렇게 하면 누군가가 컴퓨터를 켜두고 유휴 상태로 두었다는 이유로 불필요한 가져오기를 방지할 수 있습니다.
브라우저 탭이 다시 활성화되면 그때 데이터를 가져옵니다.
 

Overview of the design (전체적인 디자인)


SWR fetcher는 다음 기능을 지원합니다.
  • "온라인 상태" 및 "브라우저 탭 포커스 상태"를 추적하여 새로 고침을 일시 중지할 때를 알 수 있습니다. 네트워크 연결이 없거나 사용자가 응용 프로그램을 사용하지 않는 경우 새로고침하고 싶지 않습니다.
  •  라이브러리 클라이언트는 상태 시스템에 이벤트를 보내 현재 가져오지 않아야 함을 나타낼 수 있습니다.
    •  사용자가 로그인되어 있지 않거나 특정 데이터 접근 권한이 없습니다.
    •  우리는 이 데이터가 필요하지 않은 애플리케이션의 상태에 존재할 수 있습니다. (필요한 데이터만)
  •  새로 고침 시간 간격을 설정할 수 있습니다.
    • 데이터의 특성에 따라 새로 고침 사이에 몇 초, 1분, 1시간 또는 하루가 소요될 수 있습니다.
    • 상태 머신이 활성화된 경우 지정된 시간이 경과하면 자동으로 데이터를 다시 가져옵니다.
  • 클라이언트는 "부실" 데이터가 있는 경우 이를 가져오기 위해 처음에 호출되는 함수를 제공할 수 있습니다.
  • 데이터 가져오기에 대한 세부 사항은 클라이언트에게 맡겨집니다. 유일한 요구 사항은 fetch 함수가 데이터를 resolve하는 promise를 반환한다는 것입니다.
    • 가져오기(fetch) 함수는 또한 새로운 데이터가 존재하지 않았음을 나타내기 위해 specialUNMODIFIED 값을 반환할 수 있습니다.
    • 이는 일반적으로 가져오기 요청이 etags 또는 If-Modified-Since 헤더를 사용하고 서버에서 데이터가 변경되지 않았음을 나타낼 때 발생합니다.
  • fetcher 함수에는 새로운 데이터가 도착하거나 오류가 발생했을 때 호출하는 함수를 제공할 수 있습니다.
  • 오류가 발생하면 지수 백오프 타이머(exponential backoff timer)를 사용하여 가져오기가 자동으로 재시도됩니다.
인기 있는 SWR 라이브러리는 여기에서 구현하지 않을 몇 가지 다른 기능을 지원합니다.
  • 캐시 관리
  • 단일 상태 머신으로 여러 클라이언트 관리
  • 페이징/무한 "추가 가져오기" 기능.
  • 서버에서 받은 마지막 데이터가 있는 데이터에 보류 중인 돌연변이를 병합합니다.
이러한 기능의 대부분은 fetcher 상태 시스템을 수정하지 않고 추가할 수 있습니다.
 
주 : 나머지 기능은 https://xstate-catalogue.com/ 를 보고 add on

When to Fetch


첫째, 페처는 이전 페치 이후 충분한 시간이 경과할 때까지 기다립니다.
지금 바로 가져와야 한다는 것을 알고 있다면 강제 새로 고침 이벤트로 그렇게 하도록 지시할 수 있습니다.
 
다음으로 브라우저 탭에 포커스가 있고 인터넷이 사용 가능한지 확인합니다.
아무도 관심을 기울이지 않거나 어쨌든 실패할 경우 가져오고 싶지 않습니다.
fetcher 함수 자체도 활성화해야 합니다. 일반적으로 이것은 사용자가 데이터를 사용하는 응용 프로그램의 일부에 있음을 의미합니다.
예를 들어 Svelte에서 fetcher는 스토어에 연결될 수 있습니다.
스토어가 첫 번째 구독자를 얻으면 가져오기를 활성화하고 구독자가 0이 되면 더 이상 데이터를 사용하지 않으므로 가져오기를 다시 비활성화합니다.
 
활성화하는 것 외에도 페처가 작동하도록 허용되어야 합니다.
이것은 enabled 설정과 매우 유사하지만, 강제 새로 고침 이벤트도 무시합니다.
사용자가 아직 로그인하지 않았거나 제대로 가져오기 위해 필요한 다른 정보가 아직 없는 경우 가져오기를 허용하지 않을 수 있습니다.

Retrying on error


가져오기가 실패하면 상태 시스템이 자동으로 재시도합니다. 지수 백오프를 사용합니다.
즉, 각 페치 실패 후 이전 시도보다 2배 더 오래 기다립니다.
따라서 1초 후에 다시 시도하고 여전히 실패하면 2초 후에 다시 시도하고 4초 후에 다시 시도할 수 있습니다.
또한 최대 재시도 기간이 있어 몇시간씩 기다리고 있지는 않습니다.
 

Quick XState Overview


XState는 유한 상태 머신인 Statechart를 구현하기 위한 유용한 기능으로 확장된 Javascript 라이브러리입니다.

Events

이벤트는 일부 동작을 트리거하기 위해 상태 머신에 전송되는 값일 뿐입니다.
각 상태는 고유한 전환 및 작업 집합으로 이벤트를 처리하고
상태 머신은 현재 상태가 이벤트를 처리하지 않는 경우 실행되는 전역 처리기를 정의할 수도 있습니다.
XState 머신에는 이벤트를 보내는 send 기능이 있습니다.
이벤트에는 일부 데이터도 포함될 수 있으며 이벤트에 의해 트리거된 액션은 해당 데이터를 이용할 수 있습니다.
 

Actions

액션은 상태 머신이 머신의 다른 부분과 상호 작용하는 한 가지 방법입니다.
액션에 의해 트리거되거나 상태에 들어가거나 나올 때 실행될 수 있습니다.
 
XState에는 이벤트를 보내거나 상태 머신의 컨텍스트를 업데이트하는 것과 같은 액션을 수행하는 특별한 액션 타입이 있습니다. (send,assign)
액션은 일반적인 함수일 수도 있습니다.
SWR 페처의 경우 모든 작업은 receive 콜백을 호출하는 일반 함수이거나
내부 컨텍스트를 업데이트하는 특수 assign action입니다.

More details about actions at Actions | XState Docs.

상태 정의
상태 정의는 상태 머신이 특정 시점에 이벤트에 응답하는 방법을 정의합니다.
XState의 상태는 액션을 트리거하거나 프로미스와 같은 비동기 프로세스를 실행할 수도 있습니다.
 
현재 상태는 상태 머신의 출력입니다.
즉, 상태 머신의 사용자는 현재 상태가 무엇인지 확인하고 이를 기반으로 행동할 수 있습니다.
 

상태 기계 컨텍스트

컨텍스트는 상태 머신과 관련된 임의의 데이터 구조일 뿐입니다.
컨텍스트에 대해 생각하는 유용한 방법은 상태는 유한하지만 컨텍스트는 무한 데이터에 대한 것입니다.
여기에는 상태 다이어그램만으로는 표현하기 어렵거나 불가능한 타임스탬프, 카운터 및 기타 데이터(이름 등의 무한스트링 입력)가 포함됩니다.
컨텍스트는 상태 머신의 동작을 변경하는 데 사용할 수 있으며 상태 머신 사용자도 컨텍스트를 볼 수 있습니다.
 

Implementation(구현)


Fetcher 생성 옵션

  • fetcher는 데이터를 가져오는 함수입니다. 상태 머신은 새로 고칠 때마다 이 함수를 호출합니다.
  • receive는 일부 데이터를 수신했거나 오류가 발생했을 때 페처에서 호출하는 함수입니다. 부작용과 관련한, fetcher의 출력입니다.
  • initialData는 첫 번째 가져오기가 성공하기 전에 사용할 데이터를 반환하는 선택적 함수입니다. 해당 함수가 제공된 경우 페처는 처음 생성될 때 이 함수를 호출합니다. 이것은 일반적으로 일종의 캐시에서 읽힙니다.
  • key는 fetcher 및 initialData 함수에 전달되는 값입니다. fetcher는 해당 키가 주어지지 않으면 키를 사용하지 않습니다.
  • name은 디버그 출력에 사용되는 문자열입니다. 제공되지 않으면 기본적으로 key로 설정됩니다.
  • autoRefreshPeriod는 데이터를 다시 새로 고칠 때까지 기다려야 하는 시간을 결정합니다.
  • maxBackoff는 오류 후 재시도할 때 가져오기 사이에 대기하는 가장 긴 시간입니다.
  • initialPermittedinitialEnabled는 페처가 생성될 때 허용되고 활성화되어야 하는지 여부를 나타냅니다. 기본값은 true이지만 false인 경우 상태 시스템은 관련 이벤트를 가져올 수 있을 때까지 기다립니다.

상태 기계 컨텍스트 구현

fetcher는 컨텍스트에 다음 값을 유지합니다.

  • lastRefresh는 이전 새로 고침이 발생한 시간을 기록합니다. 이를 통해 다음 새로 고침이 언제 발생해야 하는지 계산할 수 있습니다.
  • retries는 가져오기에 실패하고 다시 시도한 횟수입니다.
  • reportedError는 우리가 실패하고 가져오기 오류를 보고했는지 여부를 나타냅니다. 이는 동일한 오류를 반복해서 보고하지 않도록 하기 위한 것입니다.
  • storeEnabled, browserEnabledpermitted는 저장소를 새로 고칠 수 있는지 여부를 추적합니다. 이것들은 또한 머신의 상태와 연관되어 있지만 일부 이벤트는 새로 고침을 강제할 수 있으며 이러한 플래그를 보고 새로 고침이 완료된 후 어떤 상태로 돌아갈지 확인하는 것이 유용합니다.

상태 기계 상태 구현

이 모든 설명과 디자인 작업에도 불구하고 실제 상태 머신은 상당히 간단합니다.
6개의 상태와 몇 가지 지원 논리가 있습니다.

maybeStart

이것은 초기 상태이며 상태 머신은 다른 가져오기를 스케줄 해야 할 때마다 이 상태로 돌아옵니다.
모든 곳에서 논리를 다시 구현하는 대신 다른 상태가 여기에서 전환하여 다음에 수행할 작업을 파악할 수 있도록 존재합니다.
 
상태 차트 용어에서 즉시 다른 상태로 전환되는 상태를 condition state라고 합니다.
maybeStart: {
  always: [
    { cond: 'not_permitted_to_refresh', target: 'notPermitted' },
    { cond: 'can_enable', target: 'waitingForRefresh' },
    { target: 'disabled' },
  ],
},
always 키는 이벤트나 딜레이를 기다리지 않고 이러한 전환을 즉시 실행하도록 XState에 지시합니다.
컨텍스트의 값이 새로 고침이 현재 허용하지 않음을 나타내면 notPermitted 또는 disabled 상태로 이동합니다.
지금 새로 고침이 허용되면 waitToRefresh로 전환됩니다.

XState Guards

이러한 전환은 전환이 실행되기 위해 참이어야 하는 조건을 나타내는 cond 키워드를 사용합니다.

XState는 이러한 조건 가드를 호출하며 상태 머신 설정은 다음과 같습니다.

guards: {
    not_permitted_to_refresh: (ctx) => !ctx.permitted,
    permitted_to_refresh: (ctx) => ctx.permitted,
    can_enable: (ctx) => {
      if (!ctx.storeEnabled || !ctx.permitted) {
        return false;
      }

      if (!ctx.lastRefresh) {
        // Refresh if we haven’t loaded any data yet.
        return true;
      }

      // Finally, we can enable if the browser tab is active.
      return ctx.browserEnabled;
    },
  },
상태 머신의 새로 고침 허용 여부와 관련된 두 개의 가드와 페처가 페치를 스케줄할 수 있는지 여부와 관련된 모든 조건을 확인하는 또 다른 가드가 있습니다.

글로벌 이벤트 핸들러

상태 머신의 전역 이벤트 핸들러는 fetch 허용 여부와 관련된 컨텍스트 정보를 업데이트한 다음
다음 작업을 파악하기 위해 maybeStart 상태로 전환합니다.
 
이러한 핸들러는 상태 외부에서 정의되므로 현재 상태에 이벤트에 대한 자체 핸들러가 없을 때마다 실행됩니다.
on: {
    FETCHER_ENABLED: { target: 'maybeStart', actions: 'updateStoreEnabled' },
    SET_PERMITTED: { target: 'maybeStart', actions: 'updatePermitted' },
    BROWSER_ENABLED: {
      target: 'maybeStart',
      actions: 'updateBrowserEnabled',
    },
  },

 

권한 없음(notPermitted), 비활성화(desabled)

현재 가져오기가 허용되지 않으면 mayStart 상태가 notPermitted 상태로 전환됩니다.
notPermitted 상태에서는 전역 이벤트 핸들러를 제외하고는 아무 것도 허용되지 않습니다.
이 상태는 또한 마지막 새로 고침에 대한 정보를 지우고 null 데이터를 receive 함수로 보냅니다.
 
desabled된 상태에서 상태 머신은 다시 가져오기를 예약하는 데 필요한 이벤트를 수신할 때까지 유휴 상태에 있습니다.
그러나 새로 고침이 자동으로 발생하지 않더라도 클라이언트는 FORCE_REFRESH 이벤트를 사용하여 새로 고침을 트리거할 수 있습니다.
// Not permitted to refresh, so ignore everything except the global events that might permit us to refresh.
notPermitted: {
  entry: ['clearData', 'clearLastRefresh'],
},
// Store is disabled, but still permitted to refresh so we honor the FORCE_REFRESH event.
disabled: {
  on: {
    FORCE_REFRESH: {
      target: 'refreshing',
      cond: 'permitted_to_refresh',
    },
  },
},

waitingForRefresh

새로 고침이 활성화된 동안 상태 시스템은 새로 고칠 시간이 될 때까지 waitForRefresh 상태에서 기다립니다.

FORCE_REFRESH 이벤트는 여전히 새로 고침을 즉시 트리거할 수 있습니다.

waitingForRefresh: {
  on: {
    FORCE_REFRESH: 'refreshing',
  },
  after: {
    nextRefreshDelay: 'refreshing',
  },
}

Delays

상태의 after key는 다른 어떤 것도 먼저 전환을 일으키지 않은 경우 특정 시간 후에 발생할 동작을 정의할 수 있습니다.
모든 전환과 마찬가지로 원하는 경우 cond 값으로 보호할 수 있습니다.
delay는은 고정되거나 가변적일 수 있습니다. 고정 지연은 단순히 지연 값을 키로 사용합니다.
after: {
  400: 'slowLoading'
}​
XState는 또한 동적 지연을 지원하며 이것이 우리가 여기서 사용하는 것입니다.
동적 지연은 상태 머신 설정의 지연 섹션에서 정의되며
각 지연 함수는 대기할 밀리초 수를 반환합니다. waitForRefresh 상태는 nextRefreshDelay 함수를 사용합니다.
delays: {
  nextRefreshDelay: (context) => {
    let timeSinceRefresh = Date.now() - context.lastRefresh;
    let remaining = autoRefreshPeriod - timeSinceRefresh;
    return Math.max(remaining, 0);
  },
  errorBackoffDelay: /* details later */,
},​
기능 자체는 매우 간단합니다. 이전 새로 고침이 발생한 시간과 다음 새로 고침이 만료될 때까지 기다려야 하는 시간을 확인합니다.
특히 delay는 setTimeout 함수를 사용하고 모든 주요 브라우저 구현은 지연 시간을 측정하기 위해 부호 있는 32비트 정수를 사용합니다.
 
즉, 약 24일보다 긴 지연은 롤오버되어 잘못된 동작이 발생합니다.
따라서 어떤 이유로 그렇게 오래 지연시키려면 작동하도록 추가 코드를 빌드해야 합니다.

리프레시

refreshing 상태는 공급된 fetcher 함수를 호출하고 새 데이터가 있을 때 클라이언트에 알립니다.
refreshing: {
  on: {
    // Ignore the events while we're refreshing but still update the
    // context so we know where to go next.
    FETCHER_ENABLED: { target: undefined, actions: 'updateStoreEnabled' },
    SET_PERMITTED: { target: undefined, actions: 'updatePermitted' },
    BROWSER_ENABLED: {
      target: undefined,
      actions: 'updateBrowserEnabled',
    },
  },
  // An XState "service" definition
  invoke: {
    id: 'refresh',
    src: 'refresh',
    onDone: {
      target: 'maybeStart',
      actions: 'refreshDone',
    },
    onError: {
      target: 'errorBackoff',
      actions: 'reportError',
    },
  },
},

Global Event Handler Overrides

refreshing 상태는 여전히 관련있는 액션을 호출하지만 상태 이동 대상(undefined)이 없는 이벤트에 대한 핸들러를 정의합니다.
 
이렇게 하면 컨텍스트가 계속 업데이트되어 다음 번에 MaybeStart가 올바른 작업을 수행할 수 있지만
가져오기가 발생하는 동안 상태 머신이 disabled된 경우에는 너무 빨리 상태를 떠나 가져오기를 중단하지 않습니다.
 
on: {
    FETCHER_ENABLED: { target: 'maybeStart', actions: 'updateStoreEnabled' },
    SET_PERMITTED: { target: 'maybeStart', actions: 'updatePermitted' },
    BROWSER_ENABLED: {
      target: 'maybeStart',
      actions: 'updateBrowserEnabled',
    },
  },

XState Services

XState는 서비스를 사용하여 비동기 작업을 수행합니다. 몇 가지 다른 타입의 서비스가 있습니다.
  • Promise가 실행된 다음 resolve하거나 reject합니다.
  • rxjs 라이브러리에 구현된 것과 같은 Observable은 여러 이벤트를 보낸 다음 완료할 수 있습니다.
  • 서비스는 또한 현재 상태 시스템과 앞뒤로 통신하는 전체 상태 머신이 될 수도 있습니다.
    • 호출된 머신이 최종 상태가 되면 서비스가 완료된 것으로 간주됩니다.

상태의 invoke 개체는 서비스를 정의합니다. src 키는 호출할 서비스를 나타내며 서비스 타입에 따라 onDone 및 onError는 수행할 다음 전환 및 액션을 정의합니다.

여기서는 클라이언트가 제공한 fetcher 함수를 호출하고 프라미스를 반환하는 하나의 서비스만 사용합니다.

 

결과 다루기

result 핸들러는 비교적 간단합니다.
가져오기가 성공하면 상태 머신은 refreshDone 액션을 실행한 다음 다음 액션을 파악하기 위해 maybeStart로 돌아갑니다.
onDone: {
  target: 'maybeStart',
  actions: 'refreshDone',
},
refreshDone 액션은 새로 고침이 발생한 시간을 기록하고 재시도 정보를 지운 다음 receive 콜백을 호출합니다.
이는 assign 액션으로 수행되므로 반환 값이 기존 컨텍스트와 병합됩니다.
refreshDone: assign((context, event) => {
  let lastRefresh = Date.now();
  let updated = {
    lastRefresh,
    retries: 0,
    reportedError: false,
  };

  if(event.data !== UNMODIFIED && context.permitted) {
    receive({ data: event.data, timestamp: lastRefresh });
  }

  return updated;
})
가져오기에서 오류가 반환되면 이를 기록하고 다시 시도할 준비를 합니다.
아래에 설명된 errorBackoff 상태는 다음 재시도 대기를 처리합니다.
onError: {
  target: 'errorBackoff',
  actions: 'reportError',
},
reportError 액션은 오류를 보고합니다
reportError: assign((context: Context, event) => {
  // Ignore the error if it happened because the browser went offline while fetching.
  // Otherwise report it.
  if (
    !context.reportedError &&
    browserStateModule.isOnline() // See the Github repo for this function
  ) {
    receive({ error: event.data });
  }
  return {
    reportedError: true,
  };
}),

errorBackoff

가져오기가 실패하면 상태 시스템은 오류 백오프 상태로 들어가고 재시도 마다 더 긴 지연 시간을 두고 대기합니다.
errorBackoff: {
  entry: ‘incrementRetry’,
  after: {
    errorBackoffDelay: ‘refreshing’,
  },
},
incrementRetry는 재시도 횟수에 1을 추가합니다.
incrementRetry: assign({ retries: (context) => context.retries + 1 }),
그리고 errorBackoffDelay 함수는 지수 백오프 알고리즘을 사용하여 대기 시간을 계산합니다.
delays: {
  errorBackoffDelay: (context, event) => {
    const baseDelay = 200;
    const delay = baseDelay * (2 ** context.retries);
    return Math.min(delay, maxBackoff);
  },
}

앱에서 사용하기


이 페처를 컴포넌트에서 직접 사용하고 receive 콜백이 관련 컴포넌트 상태를 업데이트하도록 할 수 있습니다.
구성 요소 간에 공유되는 데이터의 경우 일반적으로 다음 예와 유사한 Svelte 스토어로 페처를 래핑합니다.
import { writable } from 'svelte/store';

export function autoFetchStore({url, interval, initialDataFn}) {
  var store = writable({},  () => {
    // When we get our first subscriber, enable the store.
    f.setEnabled(true);
    // Then disable it when we go back to zero subscribers.
    return () => f.setEnabled(false);
  });

  var f = fetcher({
    key: url,
    autoRefreshPeriod: interval,
    fetcher: () => fetch(url).then((r) => r.json()),
    receive: store.set,
    initialData: initialDataFn,
    initialEnabled: false,
  });

  return {
    subscribe: store.subscribe,
    destroy: f.destroy,
    refresh: f.refresh,
  };
}

 

이게 다입니다! 성가신 비트와 조건이 포함된 복잡한 코드 조각이 상태 머신으로 구현되면 매우 간단하고 이해하기 쉽습니다.
여기에서 코드의 전체 버전을 찾을 수 있습니다. this Github repository.
주 : 위의 복잡한 내용의 구현이 얼마나 읽기 쉬운지 repo에 들어가서 확인해보자!
반응형