← Назад к вопросам

Как реализовать запрос через fetch без библиотек?

2.0 Middle🔥 111 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI3 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Реализация HTTP запросов через fetch API

Fetch API — это встроенный в браузер способ делать HTTP запросы без каких-либо библиотек. Это стандартное решение для современного JavaScript.

Базовый GET запрос

fetch('https://api.example.com/users')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error('Error:', error))

POST запрос с данными

fetch('https://api.example.com/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer token'
  },
  body: JSON.stringify({ name: 'John', email: 'john@example.com' })
})
  .then(response => response.json())
  .then(data => console.log('Created:', data))
  .catch(error => console.error('Error:', error))

Обработка ошибок и статус кодов

async function fetchData(url) {
  try {
    const response = await fetch(url)
    if (!response.ok) {
      throw new Error(`HTTP Error: ${response.status}`)
    }
    const data = await response.json()
    return data
  } catch (error) {
    console.error('Fetch failed:', error)
    throw error
  }
}

Реализация timeout через Promise.race

function fetchWithTimeout(url, timeoutMs = 5000) {
  return Promise.race([
    fetch(url),
    new Promise((_, reject) =>
      setTimeout(() => reject(new Error('Timeout')), timeoutMs)
    )
  ])
}

AbortController для отмены запросов

const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), 5000)

fetch('https://api.example.com/data', {
  signal: controller.signal
})
  .then(r => r.json())
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('Request was cancelled')
    }
  })
  .finally(() => clearTimeout(timeoutId))

Загрузка файла

const formData = new FormData()
formData.append('file', fileInput.files[0])
formData.append('name', 'My File')

fetch('/api/upload', {
  method: 'POST',
  body: formData
})
  .then(r => r.json())

Параллельные запросы

Promise.all([
  fetch('/api/users').then(r => r.json()),
  fetch('/api/posts').then(r => r.json())
])
  .then(([users, posts]) => {
    console.log('All loaded:', { users, posts })
  })

Promise.allSettled([
  fetch('/api/users').then(r => r.json()),
  fetch('/api/slow').then(r => r.json())
])
  .then(results => {
    results.forEach((result, index) => {
      if (result.status === 'fulfilled') {
        console.log(`Request ${index} succeeded:`, result.value)
      } else {
        console.log(`Request ${index} failed:`, result.reason)
      }
    })
  })

Полезная wrapper функция

class API {
  static async request(url, options = {}) {
    const { method = 'GET', body, headers = {}, timeout = 10000 } = options
    const controller = new AbortController()
    const timeoutId = setTimeout(() => controller.abort(), timeout)
    
    try {
      const response = await fetch(url, {
        method,
        headers: { 'Content-Type': 'application/json', ...headers },
        body: body ? JSON.stringify(body) : undefined,
        signal: controller.signal
      })
      
      if (!response.ok) throw new Error(`HTTP ${response.status}`)
      return response.json()
    } catch (error) {
      if (error.name === 'AbortError') throw new Error('Request timeout')
      throw error
    } finally {
      clearTimeout(timeoutId)
    }
  }
  
  static get(url) { return this.request(url, { method: 'GET' }) }
  static post(url, body) { return this.request(url, { method: 'POST', body }) }
  static put(url, body) { return this.request(url, { method: 'PUT', body }) }
  static delete(url) { return this.request(url, { method: 'DELETE' }) }
}

API.get('/api/users').then(users => console.log(users))
API.post('/api/users', { name: 'John' }).then(user => console.log(user))

Преимущества и ограничения

Преимущества:

  • Встроен в браузер, не нужны зависимости
  • Promise-based синтаксис
  • Современный стандартный подход
  • Поддерживается везде кроме IE 11

Ограничения:

  • Нет встроенного timeout (нужен AbortController)
  • Нет встроенного retry (нужно писать самому)
  • CORS требует правильной настройки
  • Нет автоматического преобразования данных

Для production часто пишут wrapper над Fetch или используют axios.