Moderní tvorba webových aplikací

O webu

Sleep v JavaScriptu

Jak implementovat sleep/delay funkcionalitu v JavaScriptu pomocí Promise a async/await

6 minut

JavaScript nemá nativní sleep() funkci jako jiné programovací jazyky. Můžeme ji ale snadno implementovat pomocí Promise a setTimeout().

Základní implementace

const sleep = ms => {
  return new Promise(resolve => setTimeout(resolve, ms))
}

const funkce = async () => {
  // kód před čekáním
  await sleep(5000)
  // nějaký kód, co se spustí po 5000 ms
}

Alternativní implementace

Sleep s reject možností

const sleep = (ms, shouldReject = false) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (shouldReject) {
        reject(new Error('Sleep interrupted'))
      } else {
        resolve()
      }
    }, ms)
  })
}

Užitečné pro simulaci chybových stavů nebo testování error handlingu:

const testErrorHandling = async () => {
  try {
    await sleep(2000, true) // simuluje chybu po 2 sekundách
    console.log('Toto se nevypíše')
  } catch (error) {
    console.log('Zachycena chyba:', error.message)
  }
}

// Použití pro testování timeoutů
const simulateTimeout = async () => {
  const timeoutPromise = sleep(5000, true)
  const dataPromise = fetch('/api/data')
  
  try {
    const result = await Promise.race([dataPromise, timeoutPromise])
    return result
  } catch (error) {
    console.log('Timeout nebo chyba:', error.message)
  }
}

Sleep s možností zrušení

const sleepWithAbort = (ms) => {
  let timeoutId
  const promise = new Promise(resolve => {
    timeoutId = setTimeout(resolve, ms)
  })
  
  promise.abort = () => {
    clearTimeout(timeoutId)
  }
  
  return promise
}

// Použití
const sleepPromise = sleepWithAbort(5000)
setTimeout(() => sleepPromise.abort(), 2000) // zruší sleep po 2s

Praktické příklady

Simulace API volání

const simulateApiCall = async (data) => {
  await sleep(1000 + Math.random() * 2000) // náhodné zpoždění 1-3s
  return { success: true, data }
}

Sekvenční zpracování

const processItems = async (items) => {
  for (const item of items) {
    console.log(`Zpracovávám: ${item}`)
    await sleep(1000) // pauza mezi položkami
  }
}

Často se hodí v případě opakovaného volání cizích API, aby nedošlo k zahlcení a chybě 429 Too Many Requests.

Při lokalizaci jedné aplikace po jednotlivých částech přes OpenAI API používám sleep pro přidávání prodlevy mezi requesty, když dojde k chybě 429. Tím se vyhnu zahlcení API a zajistím plynulé zpracování celé aplikace.

Dynamický sleep

S hodnotou prodlevy si jde pohrát tak, aby se dynamicky měnila podle odpovědi ze serveru, tj. se prodlužovala při neúspěchu.

const translateWithDynamicRetry = async (text, targetLanguage) => {
  let retryCount = 0
  let baseDelay = 1000
  
  while (retryCount < 5) {
    try {
      const response = await fetch('https://api.openai.com/v1/chat/completions', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${API_KEY}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          model: 'gpt-3.5-turbo',
          messages: [{
            role: 'user',
            content: `Přelož tento text do ${targetLanguage}: ${text}`
          }]
        })
      })
      
      if (response.status === 429) {
        const delay = baseDelay * Math.pow(2, retryCount)
        
        console.log(`Rate limit dosažen, čekám ${delay}ms (pokus ${retryCount + 1})`)
        await sleep(delay)
        retryCount++
        continue
      }
      
      return await response.json()
    } catch (error) {
      console.error('Chyba při překladu:', error)
      retryCount++
      await sleep(baseDelay * Math.pow(2, retryCount))
    }
  }
  
  throw new Error('Překročen maximální počet pokusů')
}

Některé API vrací Retry-After hlavičku s doporučeným časem čekání. Pokud je k disposici, může se použít.

Pozor na blokování

Sleep funkce neblokuje hlavní vlákno:

const demo = async () => {
  console.log('Start')
  await sleep(3000)
  console.log('Konec')
}

demo()
console.log('Toto se vypíše okamžitě')

Výstup:

Start
Toto se vypíše okamžitě
Konec (po 3 sekundách)

Kdy sleep nepoužívat

Řešení časté chyby: místo čekání na čas je lepší počkat na skutečný stav.

Zvlášť začínající programátory může svádět řešit problémy tak, že si někam přidají sleep jako rychlou opravu chyby.

const checkStatus = async () => {
  await sleep(2000) // předpokládáme, že bude hotovo
  return getStatus()
}

Lepší je počkat na skutečný výsledek:

const checkStatus = async () => {
  const response = await fetch('/api/status')
  return response.json()
}

Nebo použít callbacky místo sleep.

Závěr

Sleep funkce je užitečná pro:

  • Simulaci API volání
  • Rate limiting
  • Sekvenční zpracování dat
  • Debugging a testování

Doporučuji používat async/await zápis pro čitelnější kód a lepší zpracování chyb.

Související články

JavaScript Battery API

Jak v JS zjistit stav baterie, co dnes funguje a kdy API nepoužívat.

3 minuty

Web jecas.cz píše Bohumil Jahoda, kontakt
Seznam všech článků
2013–2025