Предотвратить многократное обновление токенов с помощью API React Hook - PullRequest
0 голосов
/ 13 марта 2020

У меня есть хук API под названием useAPICall, который имеет обратный вызов call. Этот обратный вызов проверяет, не истек ли токен, хранящийся в реагирующей переменной с именем auth, обновляет его при необходимости, затем вызывает функцию извлечения.

Я вызываю его в моем компоненте так:

const [api] = useAPICall();

useEffect(() => {
    api.call('/api/settings/mine/').then(data => {
        // do stuff here
    });
}, []);

И это работает. Он проходит поток аутентификации и вызывает API. Но если у меня useAPICall есть несколько компонентов, которые все пытаются вызвать API примерно в одно и то же время (например, загрузка холодной страницы), то каждый его экземпляр вызывает метод токена refre sh, потому что срок его действия истек.

Информация об аутентификации (access / refre sh токены) хранится в реагирующей глобальной переменной auth, например ниже, внутри хука useAPICall.js

import React, {useCallback, useContext, useEffect, useMemo, useState} from 'react';
import {useDispatch, useGlobal} from 'reactn';


export function useAPICall() {
    const [auth, setAuth] = useGlobal('auth');
    const authRefreshSuccess = useDispatch('authRefreshSuccess');

    async function refreshToken() {
        console.log('Refreshing access token...');
        const authResponse = await fetch('/api/auth/token/refresh/', {
            method: 'POST',
            credentials: 'same-origin',
            body: JSON.stringify({refresh: auth.refresh.token}),
            headers: {
                'Content-Type': 'application/json',
            },
        });
        if (authResponse.ok) {
            const authToken = await authResponse.json();
            await authRefreshSuccess(authToken);
            return authToken.access;
        }
    }

    function isTokenExpired() {
        if (localAuth.access)
            return auth.access.exp <= Math.floor(Date.now() / 1000);
        else
            return false;
    }

    const call = useCallback(async (endpoint, options={headers: {}}) => {
        console.log('performing api call');
        token = undefined;

        if (isTokenExpired())
            token = await refreshToken();
        else
            token = localAuth.access.token;

        const res = await fetch(endpoint, {
            ...options,
            headers: {
                ...options.headers,
                'Authorization': `Bearer ${token}`,
            }
        });
        if (!res.ok)
            throw await res.json();
        return res.json();

    }, []);

    const anonCall = useCallback(async (endpoint, options={}}) => {
        const res = await fetch(endpoint, options);
        if (!res.ok)
            throw await res.json();
        return res.json();

    }, []);


    const api = useMemo(
        () => ({
            call,
            anonCall,
        }),
        [call, anonCall,]
    );

    return [api]
}

Как я могу предотвратить их запустить метод refre sh несколько раз?

Если есть лучший способ (без избыточности) иметь универсальный поток API (где любой вызов API сначала проверяет токен доступа и при необходимости обновляет sh), тогда я готов выслушать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...