Desduplicação de Recursos com React Suspense: Prevenindo Requisições Duplicadas | MLOG | MLOG

Agora, o UserResource verifica se um recurso já existe no cache. Se existir, o recurso em cache é retornado. Caso contrário, uma nova requisição é iniciada e a promise resultante é armazenada no cache. Isso garante que apenas uma requisição seja feita para cada userId único.

2. Usando uma Biblioteca de Cache Dedicada (ex: `lru-cache`)

Para cenários de cache mais complexos, considere usar uma biblioteca de cache dedicada como lru-cache ou similar. Essas bibliotecas fornecem recursos como remoção de itens do cache com base no Menos Recentemente Usado (LRU) ou outras políticas, o que pode ser crucial para gerenciar o uso de memória, especialmente ao lidar com um grande número de recursos.

Primeiro, instale a biblioteca:

            
npm install lru-cache

            

Em seguida, integre-a ao seu UserResource:

            
import React, { Suspense } from 'react';
import LRUCache from 'lru-cache';

const fetchUser = (userId) => {
  console.log(`Buscando usuário com ID: ${userId}`); // Simula uma requisição de rede
  return new Promise(resolve => {
    setTimeout(() => {
      resolve({ id: userId, name: `Usuário ${userId}`, email: `usuario${userId}@example.com` });
    }, 1000); // Simula a latência da rede
  });
};

const cache = new LRUCache({
  max: 100, // Número máximo de itens no cache
  ttl: 60000, // Tempo de vida em milissegundos (1 minuto)
});

const UserResource = (userId) => {
  if (!cache.has(userId)) {
    let promise = null;
    let status = 'pending'; // pendente, sucesso, erro
    let result;

    const suspender = fetchUser(userId).then(
      (r) => {
        status = 'success';
        result = r;
        cache.set(userId, {
          read() {
            return result;
          },
        });
      },
      (e) => {
        status = 'error';
        result = e;
        cache.set(userId, {
          read() {
            throw result;
          },
        });
      }
    );

    cache.set(userId, {
        read() {
            if (status === 'pending') {
                throw suspender;
            } else if (status === 'error') {
                throw result;
            }
            return result;
        }
    });
  }

  return cache.get(userId);
};


const UserProfile = ({ userId }) => {
  const user = UserResource(userId).read();
  return (
    

Perfil do Usuário

ID: {user.id}

Nome: {user.name}

Email: {user.email}

); }; const UserDetails = ({ userId }) => { const user = UserResource(userId).read(); return (

Detalhes do Usuário

ID: {user.id}

Nome: {user.name}

); }; const App = () => { return ( Carregando...
}> ); }; export default App;

Essa abordagem fornece mais controle sobre o tamanho e a política de expiração do cache.

3. Coalescência de Requisições com Bibliotecas como `axios-extensions`

Bibliotecas como axios-extensions oferecem recursos mais avançados, como a coalescência de requisições. A coalescência de requisições combina várias requisições idênticas em uma única requisição, otimizando ainda mais o uso da rede. Isso é particularmente útil em cenários onde as requisições são iniciadas muito próximas umas das outras no tempo.

Primeiro, instale a biblioteca:

            
npm install axios axios-extensions

            

Em seguida, configure o Axios com o adaptador de cache fornecido pelo axios-extensions.

Exemplo usando `axios-extensions` e criando um recurso:

            
import React, { Suspense } from 'react';
import axios from 'axios';
import { cacheAdapterEnhancer, throttleAdapterEnhancer } from 'axios-extensions';

const instance = axios.create({
  baseURL: 'https://api.example.com', // Substitua pelo seu endpoint de API
  adapter: cacheAdapterEnhancer(axios.defaults.adapter, { enabledByDefault: true }),
});

const fetchUser = async (userId) => {
  console.log(`Buscando usuário com ID: ${userId}`); // Simula uma requisição de rede
  const response = await instance.get(`/users/${userId}`);
  return response.data;
};


const UserResource = (userId) => {
    let promise = null;
    let status = 'pending'; // pendente, sucesso, erro
    let result;

    const suspender = fetchUser(userId).then(
        (r) => {
            status = 'success';
            result = r;
        },
        (e) => {
            status = 'error';
            result = e;
        }
    );

    return {
        read() {
            if (status === 'pending') {
                throw suspender;
            } else if (status === 'error') {
                throw result;
            }
            return result;
        },
    };
};


const UserProfile = ({ userId }) => {
  const user = UserResource(userId).read();
  return (
    

Perfil do Usuário

ID: {user.id}

Nome: {user.name}

Email: {user.email}

); }; const UserDetails = ({ userId }) => { const user = UserResource(userId).read(); return (

Detalhes do Usuário

ID: {user.id}

Nome: {user.name}

); }; const App = () => { return ( Carregando...
}> ); }; export default App;

Isso configura o Axios para usar um adaptador de cache, armazenando respostas em cache automaticamente com base na configuração da requisição. A função cacheAdapterEnhancer oferece opções para configurar o cache, como definir um tamanho máximo de cache ou tempo de expiração. O throttleAdapterEnhancer também pode ser usado para limitar o número de requisições feitas ao servidor dentro de um certo período, otimizando ainda mais o desempenho.

Melhores Práticas para Desduplicação de Recursos

Considerações Globais para Busca de Dados e Desduplicação

Ao projetar estratégias de busca de dados para um público global, vários fatores entram em jogo:

Por exemplo, um site de reservas de viagens com foco em um público global pode usar uma CDN para servir dados de disponibilidade de voos e hotéis de servidores localizados em diferentes regiões. O site também usaria uma API de conversão de moeda para exibir preços na moeda local do usuário e forneceria opções para filtrar os resultados da pesquisa com base nas preferências de idioma.

Conclusão

A desduplicação de recursos é uma técnica de otimização essencial para aplicações React que usam Suspense. Ao prevenir requisições duplicadas de busca de dados, você pode melhorar significativamente o desempenho, reduzir a carga no servidor e aprimorar a experiência do usuário. Seja escolhendo implementar um cache simples de promises ou aproveitando bibliotecas mais avançadas como lru-cache ou axios-extensions, o fundamental é entender os princípios subjacentes e escolher a solução que melhor se adapta às suas necessidades específicas. Lembre-se de considerar fatores globais como CDNs, localização e acessibilidade ao projetar suas estratégias de busca de dados para um público diversificado. Ao implementar essas melhores práticas, você pode construir aplicações React mais rápidas, eficientes e amigáveis ao usuário.