From fb476e8c0eedcbabe66ce705767d19385838e65e Mon Sep 17 00:00:00 2001 From: Nonimart Date: Tue, 13 Jan 2026 15:37:11 +0100 Subject: [PATCH] TEST FIX debounce --- resources/js/filter-articles.ts | 54 +++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/resources/js/filter-articles.ts b/resources/js/filter-articles.ts index 4a8f4ac..5cbf207 100644 --- a/resources/js/filter-articles.ts +++ b/resources/js/filter-articles.ts @@ -9,18 +9,45 @@ export default function filterArticlesInit() { const sortBySelect = toolbar.querySelector('select[name="sort_by"]') as HTMLSelectElement; const rechercheInput = toolbar.querySelector('.search-bar input') as HTMLInputElement; + // Évite les courses: annule les requêtes précédentes et ignore les réponses obsolètes + let currentAbortController: AbortController | null = null; + let lastRequestId = 0; + + // Debounce simple pour la recherche + function debounce void>(fn: T, waitMs: number) { + let timeoutId: number | undefined; + return (...args: Parameters) => { + if (timeoutId) window.clearTimeout(timeoutId); + timeoutId = window.setTimeout(() => fn(...args), waitMs); + }; + } + async function hydrateArticles() { - const etiquetteValue = etiquettesSelect.value; - const auteurValue = auteursSelect.value; - const sortByValue = sortBySelect.value; - const rechercheValue = rechercheInput.value; + const etiquetteValue = etiquettesSelect?.value ?? ''; + const auteurValue = auteursSelect?.value ?? ''; + const sortByValue = sortBySelect?.value ?? ''; + const rechercheValue = rechercheInput?.value ?? ''; + + const params = new URLSearchParams({ + etiquette: etiquetteValue, + auteur: auteurValue, + sort_by: sortByValue, + recherche: rechercheValue, + }); + const url = `/wp-json/dynamiques-datas/v1/build/${currentPostType}?${params.toString()}`; + + // Annule la précédente et prépare un nouvel identifiant + if (currentAbortController) currentAbortController.abort(); + currentAbortController = new AbortController(); + const requestId = ++lastRequestId; try { - const response = await fetch( - `/wp-json/dynamiques-datas/v1/build/${currentPostType}?etiquette=${etiquetteValue}&auteur=${auteurValue}&sort_by=${sortByValue}&recherche=${rechercheValue}` - ); + const response = await fetch(url, { signal: currentAbortController.signal }); + if (!response.ok) throw new Error(`HTTP ${response.status}`); const data = await response.json(); - console.log(data); + + // Ignore si une requête plus récente a été envoyée + if (requestId !== lastRequestId) return; const articlesContainer = document.querySelector('.post-grid__list'); if (!articlesContainer) return; @@ -28,10 +55,13 @@ export default function filterArticlesInit() { updatePostCount(data.post_count); } catch (error) { + if ((error as any)?.name === 'AbortError') return; console.error('Erreur lors de la récupération des articles:', error); } } + const hydrateArticlesDebounced = debounce(hydrateArticles, 250); + function resetCurrentFilters() { if (!etiquettesSelect || !auteursSelect || !rechercheInput) return; @@ -57,7 +87,7 @@ export default function filterArticlesInit() { e.preventDefault(); setFilterByActivebutton(button as HTMLButtonElement); resetCurrentFilters(); - hydrateArticles(); + hydrateArticles(); // immédiat sur action explicite }); }); } @@ -65,15 +95,15 @@ export default function filterArticlesInit() { // Écouter les changements sur les selects if (postGridToolbarActions) { postGridToolbarActions.addEventListener('change', (e) => { - hydrateArticles(); + hydrateArticles(); // immédiat sur selects }); } sortBySelect.addEventListener('change', (e) => { - hydrateArticles(); + hydrateArticles(); // immédiat pour le tri }); rechercheInput.addEventListener('input', (e) => { - hydrateArticles(); + hydrateArticlesDebounced(); // debounce pour la saisie rapide }); // Initialiser le filtrage par boutons