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

Есть ли у браузера ограничение на количество запросов?

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

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

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

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

Ограничения браузера на количество запросов

Да, браузер имеет несколько важных ограничений на количество и характер HTTP запросов, которые он может выполнить. Это критическая информация для оптимизации веб-приложений.

Параллельные подключения на домен

Браузер имеет лимит на количество одновременных TCP подключений к одному домену. Это один из самых важных лимитов.

// Например, если вы отправляете 100 запросов на одновременно,
// браузер пропустит только 6-10 параллельных запросов
// остальные будут в очереди

const urls = Array.from({ length: 100 }, (_, i) => 
  `https://api.example.com/data/${i}`
);

Promise.all(urls.map(url => fetch(url)));
// Браузер обработает только 6-10 одновременно
// остальные 90 будут ждать в очереди

Типичные лимиты:

  • Chrome: 6 подключений на домен
  • Firefox: 6 подключений на домен
  • Safari: 6 подключений на домен
  • Edge: 6 подключений на домен

Это значит, что если вы делаете 100 запросов на один домен, они будут обработаны порциями по 6-10.

HTTP/2 и HTTP/3

С внедрением HTTP/2 и HTTP/3 ситуация улучшилась. Эти протоколы используют multiplexing — многократное использование одного подключения для нескольких запросов.

// HTTP/2 и HTTP/3 используют одно подключение для всех запросов
// Поэтому лимит на домен уже не так критичен

// Однако, каждый запрос всё ещё имеет свой номер потока
// и браузер может ограничивать количество открытых потоков

const urls = Array.from({ length: 100 }, (_, i) => 
  `https://api.example.com/data/${i}`
);

Promise.all(urls.map(url => fetch(url)));
// С HTTP/2: обработаны быстрее благодаря multiplexing
// Но всё ещё есть лимиты на количество потоков

Лимиты на типы запросов

WebSockets Лимит на количество открытых WebSocket подключений:

// Браузер может иметь лимит на общее количество WebSocket подключений
// Обычно это 256 или больше

const sockets = [];
for (let i = 0; i < 100; i++) {
  sockets.push(new WebSocket(`wss://example.com/socket/${i}`));
}
// Браузер может отклонить подключения после определённого лимита

Fetch и XMLHttpRequest Одновременные запросы ограничены:

// Это может привести к очередям запросов
const requests = [];
for (let i = 0; i < 50; i++) {
  requests.push(fetch(`https://api.example.com/data/${i}`));
}

await Promise.all(requests);
// Если все на один домен, выполняется 6-10 одновременно

Лимиты на размер

URL length Традиционный лимит на длину URL около 2048 символов, хотя браузеры часто поддерживают больше.

// ❌ Очень длинный URL
const longUrl = 'https://example.com/api?' + 
  'param=' + 'x'.repeat(10000);

fetch(longUrl);  // Может быть отклонён

// ✅ Использовать POST с телом запроса
fetch('https://example.com/api', {
  method: 'POST',
  body: JSON.stringify({ data: 'x'.repeat(10000) })
});

Размер ответа Нет строгого лимита на размер ответа, но браузер может столкнуться с проблемами памяти при очень больших ответах.

Как избежать проблем

1. Используйте HTTP/2 или HTTP/3

// Убедитесь, что сервер использует HTTP/2
// Это снижает влияние лимита на параллельные подключения

2. Группируйте запросы

// Вместо 100 отдельных запросов
const ids = Array.from({ length: 100 }, (_, i) => i);

// ❌ Плохо: 100 запросов
Promise.all(ids.map(id => fetch(`/api/item/${id}`)));

// ✅ Хорошо: 1 запрос с массивом ID
fetch('/api/items/bulk', {
  method: 'POST',
  body: JSON.stringify({ ids })
});

3. Используйте несколько доменов

// Каждый домен имеет отдельный лимит на подключения
const domains = ['api1.example.com', 'api2.example.com', 'api3.example.com'];

const requests = urls.map((url, i) => 
  fetch(`https://${domains[i % domains.length]}${url}`)
);

await Promise.all(requests);
// Теперь 6 подключений на каждый домен = 18 одновременных запросов

4. Реализуйте очередь запросов

class RequestQueue {
  constructor(maxConcurrent = 6) {
    this.maxConcurrent = maxConcurrent;
    this.running = 0;
    this.queue = [];
  }

  async add(fn) {
    if (this.running < this.maxConcurrent) {
      this.running++;
      try {
        return await fn();
      } finally {
        this.running--;
        this.process();
      }
    } else {
      return new Promise(resolve => {
        this.queue.push(() => this.add(fn).then(resolve));
      });
    }
  }

  async process() {
    while (this.queue.length && this.running < this.maxConcurrent) {
      const fn = this.queue.shift();
      await fn();
    }
  }
}

const queue = new RequestQueue(6);
const requests = urls.map(url => 
  queue.add(() => fetch(url))
);

await Promise.all(requests);

5. Используйте кэширование

const cache = new Map();

async function cachedFetch(url) {
  if (cache.has(url)) {
    return cache.get(url);
  }
  const response = await fetch(url);
  const data = await response.json();
  cache.set(url, data);
  return data;
}

// Повторные запросы берут из кэша, а не отправляют новый запрос
await cachedFetch('/api/user/1');
await cachedFetch('/api/user/1');  // из кэша

Service Workers и ограничения

Service Workers могут помочь контролировать запросы:

// В Service Worker
self.addEventListener('fetch', event => {
  // Можно перехватить и отложить запросы
  // или вернуть кэшированный ответ
  event.respondWith(
    caches.match(event.request)
      .then(response => response || fetch(event.request))
  );
});

Итог

Браузер имеет ограничения на:

  • Параллельные подключения — обычно 6 на домен
  • WebSocket подключения — зависит от браузера
  • Длина URL — около 2048 символов
  • Размер памяти — для очень больших ответов

Для оптимальной производительности:

  • Группируйте запросы
  • Используйте HTTP/2 или HTTP/3
  • Кэшируйте результаты
  • Контролируйте параллельность
  • Используйте несколько доменов если нужно

В современных браузерах с HTTP/2 эти ограничения менее критичны, но они всё ещё существуют и о них важно помнить при оптимизации.