Skip to content

Príklad: našepkávač

Našepkávač pod vyhľadávacím poľom nad endpointom GET /suggest. Ak nepotrebujete vlastný vzhľad ani správanie, rovnakú funkcionalitu poskytuje widget bez písania kódu.

Volanie z prehliadača

js
const ENDPOINT = 'https://search.api.metty.eu/suggest'

async function suggest(query, signal) {
    const params = new URLSearchParams({ key: PUBLIC_API_KEY, q: query, limit: '8' })
    const response = await fetch(`${ENDPOINT}?${params}`, { signal })

    if (!response.ok) {
        throw new Error(`suggest failed: ${response.status}`)
    }

    return response.json()
}

Odpoveď obsahuje najviac 8 návrhov dotazov a najviac 5 produktov v skrátenom tvare — bez popisu a bez zvýraznenia.

Debounce a zrušenie predchádzajúcej požiadavky

Bez debounce odošle vyhľadávacie pole požiadavku na každý stlačený znak a odpovede môžu doraziť v nesprávnom poradí. Oboje rieši AbortController:

js
let controller = null
let timer = null

input.addEventListener('input', () => {
    const query = input.value.trim()

    clearTimeout(timer)
    controller?.abort()

    if (query.length < 2) {
        render(null)
        return
    }

    timer = setTimeout(async () => {
        controller = new AbortController()

        try {
            render(await suggest(query, controller.signal))
        } catch (error) {
            if (error.name !== 'AbortError') {
                render(null)
            }
        }
    }, 150)
})

Zrušená požiadavka vyvolá AbortError; ten sa nesmie prejaviť ako chyba, pretože ide o očakávaný stav pri rýchlom písaní.

Vykreslenie

js
function render(data) {
    if (!data || (data.suggestions.length === 0 && data.products.length === 0)) {
        panel.hidden = true
        return
    }

    panel.replaceChildren(
        ...data.suggestions.map(item => option(item.query, `${item.count} produktov`)),
        ...data.products.map(product => productRow(product))
    )

    panel.hidden = false
}

Návrhy vedú na výsledkovú stránku s daným dotazom, produkty priamo na product.url. Cena je v poli price, mena katalógu v currency.

Na čo dbať

témaodporúčanie
minimálna dĺžka dotazu2 znaky; kratší dotaz neposielajte
debounce120–200 ms
rate limit1800 požiadaviek za minútu na kľúč, počíta sa na verejný kľúč
prázdna odpoveďpanel skryte, nezobrazujte hlásenie o chybe
klávesnicašípky, Enter a Escape obslúžte sami — panel nie je natívny <datalist>

Podrobnosti o parametroch a tvare odpovede nájdete v sekcii Našepkávanie.

Dokumentácia Metty