From 5c7574fd3f8c9dab78dfada955c78184eda2065f Mon Sep 17 00:00:00 2001 From: Mimi <1119186082@qq.com> Date: Tue, 4 Aug 2026 14:55:10 +0800 Subject: [PATCH] Improve Algolia search concurrency --- .../js/third-party/search/algolia-search.js | 127 ++++++++++-------- 1 file changed, 68 insertions(+), 59 deletions(-) diff --git a/source/js/third-party/search/algolia-search.js b/source/js/third-party/search/algolia-search.js index e77dcf2..1b22ab2 100644 --- a/source/js/third-party/search/algolia-search.js +++ b/source/js/third-party/search/algolia-search.js @@ -19,83 +19,92 @@ document.addEventListener('DOMContentLoaded', () => { return result; }; - let isSearching = false; - let pendingQuery = null; + let latestSearchId = 0; - const searchAlgolia = async (searchText, page = 0) => { - if (isSearching) { - pendingQuery = { searchText, page }; - return; - } - isSearching = true; + const searchAlgolia = async (searchText, page, searchId) => { + if (searchId !== latestSearchId) return; + container.setAttribute('aria-busy', 'true'); const startTime = Date.now(); - const result = await client.search({ - requests: [{ - indexName, - page, - query : searchText, - hitsPerPage : hits.per_page || 10, - attributesToRetrieve : ['permalink'], - attributesToHighlight: ['title', 'excerpt', 'excerptStrip', 'contentStripTruncate'], - highlightPreTag : '', - highlightPostTag : '' - }] - }); - const data = result.results[0]; - if (data.nbHits === 0) { - container.innerHTML = '
'; - } else { - const stats = CONFIG.i18n.hits_time - .replace('${hits}', data.nbHits) - .replace('${time}', Date.now() - startTime); - let pagination = ''; - if (data.nbPages > 1) { - pagination += ''; - } + try { + const result = await client.search({ + requests: [{ + indexName, + page, + query : searchText, + hitsPerPage : hits.per_page || 10, + attributesToRetrieve : ['permalink'], + attributesToHighlight: ['title', 'excerpt', 'excerptStrip', 'contentStripTruncate'], + highlightPreTag : '', + highlightPostTag : '' + }] + }); + if (searchId !== latestSearchId) return; - container.innerHTML = `
+ const data = result.results[0]; + if (data.nbHits === 0) { + container.innerHTML = '
'; + } else { + const stats = CONFIG.i18n.hits_time + .replace('${hits}', data.nbHits) + .replace('${time}', Date.now() - startTime); + let pagination = ''; + if (data.nbPages > 1) { + pagination += ''; + } + + container.innerHTML = `
${stats} Algolia

${pagination}`; - if (typeof pjax === 'object') pjax.refresh(container); - container.querySelectorAll('.page-number').forEach(element => { - element.addEventListener('click', async event => { - event.preventDefault(); - await searchAlgolia(searchText, Number(element.dataset.index)); + if (typeof pjax === 'object') pjax.refresh(container); + container.querySelectorAll('.page-number').forEach(element => { + element.addEventListener('click', async event => { + event.preventDefault(); + if (input.value.trim() !== searchText) return; + const searchId = ++latestSearchId; + await searchAlgolia(searchText, Number(element.dataset.index), searchId); + }); }); - }); - } - isSearching = false; - if (pendingQuery !== null && (pendingQuery.searchText !== searchText || pendingQuery.page !== page)) { - const { searchText, page } = pendingQuery; - pendingQuery = null; - searchAlgolia(searchText, page); + } + } catch (error) { + if (searchId !== latestSearchId) return; + console.warn('Algolia search failed:', error); + container.innerHTML = '
'; + } finally { + if (searchId === latestSearchId) container.removeAttribute('aria-busy'); } }; - const inputEventFunction = async () => { + const inputEventFunction = async searchId => { + if (searchId !== latestSearchId) return; const searchText = input.value.trim(); - if (searchText === '') { - container.innerHTML = '
'; - return; - } + if (searchText === '') return; // Algolia client will automatically cache the data for same queries - await searchAlgolia(searchText, 0); + await searchAlgolia(searchText, 0, searchId); }; const debouncedSearch = NexT.utils.debounce(inputEventFunction, 500); - input.addEventListener('input', debouncedSearch); + input.addEventListener('input', () => { + const searchId = ++latestSearchId; + if (input.value.trim() === '') { + container.removeAttribute('aria-busy'); + container.innerHTML = '
'; + } else { + container.setAttribute('aria-busy', 'true'); + } + debouncedSearch(searchId); + }); // Handle and trigger popup window document.querySelectorAll('.popup-trigger').forEach(element => {