프런트엔드에서 네트워크 요청 캐시

안녕하세요!



dev.to의 첫 번째 댓글!
나는 매우 엄격하다.나는 지식을 얻기 위해 학습형 창고 개발자이다.
오늘 저는 여러분과 함께 프런트엔드에서 네트워크 요청을 캐시하는 방법을 배울 것입니다.
여기서 논의된 코드는 Github에서 얻을 수 있습니다 api-cache-example.
나는 자신의 백엔드에서 시간 스탬프를 얻기 위해 작은 프로그램을 만들고 있었다.이것은 Typescript로 작성된 React와 Redux로 구성된 중형 응용 프로그램입니다.나는 axios를 나의 HTTP 클라이언트로 사용한다.
(참고로 이 코드는 Typescript로 작성되었지만 유사한 사상을 따라 자바스크립트로 쉽게 확장할 수 있습니다.)
나는 정말 클라이언트에서 나의 요청을 캐시하고 싶다. 이렇게 하면 나는 나의 API를 중복 호출할 필요가 없다.
나는 간단한 해결 방안을 생각하고 그것을 실시하기 시작했다 interceptors.
이 생각은 매우 간단하다.모든 유형의 객체를 저장할 수 있는 캐시가 있습니다.그리고 캐시 시간보다 오래 저장되면 무효가 됩니다.
간단하죠?
그럼, 우리 그것을 실시합시다!
우선, 우리는 캐시를 만들 것이다.cacheHandler.ts라는 파일을 만들 것입니다.
우리 뭐 먹어야 돼요?
논리적으로 생각하자.캐시는 두 개의 요청을 처리해야 합니다 ->
  • 상점.
  • 유효한 경우 검색합니다.
  • 우리 두 함수 store()isValid 를 합시다.
    function store(key: string, value: string) {
        const finalValue = `${value}${SEPARATOR}${Date.now().toString()}`;
        localStorage.setItem(key, finalValue);
    }
    
    function isValid(key: string): IsValidResponse {
        const value = localStorage.getItem(key);
        if (value === null) {
            return {
                isValid: false,
            };
        }
        const values = value.split(SEPARATOR);
        const timestamp = Number(values[1]);
        if (Number.isNaN(timestamp)) {
            return {
                isValid: false,
            };
        }
        const date = new Date(timestamp);
        if (date.toString() === 'Invalid Date') {
            return {
                isValid: false,
            };
        }
        if ((Date.now() - date.getTime()) < CACHE_INTERVAL) {
            return {
                isValid: true,
                value: values[0],
            };
        }
        localStorage.removeItem(key);
        return {
            isValid: false,
        };
    }
    
    자세히 살펴보면 isValid 유형 IsValidResponse 의 응답을 다음과 같이 반환합니다.
    interface IsValidResponse {
        isValid: boolean,
        value?: string,
    }
    
    우리는 상수가 부족하기 때문에 보충해 봅시다.
    const SEPARATOR = '//**//';
    const CACHE_INTERVAL = 0.2 * 60 * 1000;
    
    store()는 문자열을 받아들여 구분자와 이후의 현재 날짜를 추가하고 localStorage에 저장하는 매우 간단한 함수입니다.이것은 isValid() 구분자에 나누어 데이터와 날짜를 검색할 수 있도록 합니다.
    현재 우리는 날짜가 유효하지 않거나 만료되지 않았는지 확인해야 합니다. 호출자에게 캐시가 효력을 상실하지 않았음을 알려 줄 수 있는 부울 값을 보낼 수 있습니다.
    현재, 우리는 localStorage에 대상을 저장하는 키로 무엇을 사용해야 합니까?
    우리는 곧 이 문제에 대답할 것이다.
    이 파일here을 직접 참조할 수 있습니다.
    현재,axios 클라이언트로 이동합니다.
    먼저 클라이언트를 만듭니다.
    export const client = axios.create({ baseURL: 'http://localhost:8080/api/widget', withCredentials: true });
    
    baseURL 요청이 발송되는 위치에 따라 어떤 내용이든 가능합니다.
    나는 8080 포트에 서버가 하나 있는데, 이것은 오늘의 날씨를 포함하는 JSON 대상을 되돌려주지만, 실제로는 어떤 API를 사용할 수 있다.
    이제 차단기를 추가합니다.
    client.interceptors.request.use((request) => requestHandler(request));
    client.interceptors.response.use(
        (response) => responseHandler(response),
        (error) => errorHandler(error),
    );
    
    const whiteList = ['weather'];
    
    function isURLInWhiteList(url: string) {
        return whiteList.includes(url.split('/')[1]);
    }
    
    function responseHandler(response: AxiosResponse<any>): AxiosResponse<any> {
        if (response.config.method === 'GET' || 'get') {
            if (response.config.url && !isURLInWhiteList(response.config.url)) {
                console.log('storing in cache');
                cache.store(response.config.url, JSON.stringify(response.data));
            }
        }
        return response;
    }
    
    function errorHandler(error: any) {
        if (error.headers.cached === true) {
            console.log('got cached data in response, serving it directly');
            return Promise.resolve(error);
        }
        return Promise.reject(error);
    }
    
    function requestHandler(request: AxiosRequestConfig) {
        if (request.method === 'GET' || 'get') {
            const checkIsValidResponse = cache.isValid(request.url || '');
            if (checkIsValidResponse.isValid) {
                console.log('serving cached data');
                request.headers.cached = true;
                request.data = JSON.parse(checkIsValidResponse.value || '{}');
                return Promise.reject(request);
            }
        }
        return request;
    }
    
    아이고, 방금 지나간 코드가 많아!
    우선 봅시다isURLInWhiteList.이것은 단지 우리가 캐시에 저장되지 않은 URL을 블랙리스트에 넣을 수 있도록 하기 위해서이다.이것은 인증 루트에 사용할 수 있습니다.
    이제 responseHandler로 이동합니다.
    첫 번째if는 요청을 보냈는지 확인하는 데 사용됩니다.
    if (response.config.method === 'GET' || 'get')
    
    그렇다면 URL은 화이트리스트에 없습니까?
    if (response.config.url && !isURLInWhiteList(response.config.url))
    
    이러한 조건이 충족되면 객체를 캐시에 저장하고 키를 요청한 URL로 사용하면 됩니다.
    현재 우리는 우선 연구GET를 할 것이다.
    첫 번째if는 요청을 보냈는지 확인하는 데 사용됩니다.
    if (response.config.method === 'GET' || 'get')
    
    캐시 유효성 확인
    const checkIsValidResponse = cache.isValid(request.url || '');
    if (checkIsValidResponse.isValid) 
    
    만약 그렇다면, 이것은 캐시가 여전히 유효하다는 것을 의미한다. 우리는 응답을 보내는 것이 아니라 서비스를 제공할 수 있다.
    따라서 요청에 제목을 추가합니다. 제목은 requestHandler (어떤 내용이든 좋습니다. 이것은 제 개인적인 선호입니다.) 그리고true로 설정합니다.
    request.headers.cached = true;
    
    요청 데이터만 캐시로 설정
    request.data = JSON.parse(checkIsValidResponse.value || '{}');
    
    그리고 약속해.요청을 거절하다.
    왜?
    이렇게 하는 것은 이 요청이 즉시 발송되기 때문이다GET.여기서 우리는 cached 머리가 있는지 검사할 수 있다.만약 그렇다면, 이것은 데이터가 진정한 오류가 아니라 캐시된 것을 의미한다.그렇지 않으면, 우리는 잘못을 거절할 수 있다.
    이것이 바로 우리가 해야 할 일이다.
    function errorHandler(error: any) {
        if (error.headers.cached === true) {
            console.log('got cached data in response, serving it directly');
            return Promise.resolve(error);
        }
        return Promise.reject(error);
    }
    
    만약 캐시 헤더가 존재한다면, 우리는 약속을 되돌려 줄 것이다.axios가 이 데이터를 오류가 발생한 적이 없는 것으로 간주하기 위해 errorHandler 이 아니라 cached 에서 이 데이터를 가져옵니다.따라서 .then 호출자는 캐시가 배후에서 발생하는 것을 몰랐다!
    다른 잘못이라면 약속 하나만 대답하면 된다.반대로 정상적인 오류와 유사하게 행동하도록 거절하세요!이거 똑똑하지 않아요?
    다음과 같이 React 응용 프로그램에서 이러한 설계를 사용했습니다.

    1604밀리초에서 놀라운 3밀리초.
    이것은 비캐시 버전보다 535배 빠르다.
    상수 .catch 를 바꾸면 캐시가 검증되어야 하는 시간을 수정할 수 있습니다.
    이 항목은 my GitHub account 에서 볼 수 있습니다.
    떠나기 전 마지막 문제.어떻게 그것을 fetch와 함께 사용합니까?
    응, 어떤 문제는 독자에게 스스로 대답하도록 남겨야 해.그렇지 않으면 학습의 목적은 무엇입니까?

    좋은 웹페이지 즐겨찾기