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

Как реализуешь очередь?

2.0 Middle🔥 151 комментариев
#Soft Skills и рабочие процессы

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

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

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

Реализация очереди (Queue)

Очередь (Queue) - это структура данных с принципом FIFO (First In, First Out). На фронтенде её используют для управления асинхронными задачами, API запросами, обработкой событий.

Базовая реализация класса Queue

// Простая реализация очереди
class Queue {
  constructor() {
    this.items = [];
  }

  // Добавить элемент в конец очереди
  enqueue(element) {
    this.items.push(element);
  }

  // Получить и удалить первый элемент
  dequeue() {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items.shift();
  }

  // Посмотреть первый элемент без удаления
  front() {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items[0];
  }

  // Проверить пусто ли
  isEmpty() {
    return this.items.length === 0;
  }

  // Размер очереди
  size() {
    return this.items.length;
  }

  // Очистить всю очередь
  clear() {
    this.items = [];
  }
}

// Использование
const queue = new Queue();
queue.enqueue('задача 1');
queue.enqueue('задача 2');
queue.enqueue('задача 3');

console.log(queue.dequeue()); // "задача 1"
console.log(queue.size());     // 2

Очередь для обработки асинхронных задач

class AsyncQueue {
  constructor(concurrency = 1) {
    this.tasks = [];
    this.running = 0;
    this.concurrency = concurrency; // сколько задач выполнять параллельно
  }

  add(task) {
    return new Promise((resolve, reject) => {
      this.tasks.push({ task, resolve, reject });
      this.process();
    });
  }

  async process() {
    // Если уже выполняется максимум задач, ждем
    if (this.running >= this.concurrency) {
      return;
    }

    // Если очередь пуста, выходим
    if (this.tasks.length === 0) {
      return;
    }

    this.running++;
    const { task, resolve, reject } = this.tasks.shift();

    try {
      const result = await task();
      resolve(result);
    } catch (error) {
      reject(error);
    } finally {
      this.running--;
      this.process(); // Обработать следующую задачу
    }
  }
}

// Использование
const queue = new AsyncQueue(2); // максимум 2 параллельные задачи

const task1 = () => fetch('/api/users').then(r => r.json());
const task2 = () => fetch('/api/posts').then(r => r.json());
const task3 = () => fetch('/api/comments').then(r => r.json());

queue.add(task1).then(users => console.log('Пользователи:', users));
queue.add(task2).then(posts => console.log('Посты:', posts));
queue.add(task3).then(comments => console.log('Комментарии:', comments));

Очередь с приоритетами (Priority Queue)

class PriorityQueue {
  constructor() {
    this.items = [];
  }

  // Добавить элемент с приоритетом (меньше число = выше приоритет)
  enqueue(element, priority) {
    const item = { element, priority };
    let added = false;

    for (let i = 0; i < this.items.length; i++) {
      if (item.priority < this.items[i].priority) {
        this.items.splice(i, 0, item);
        added = true;
        break;
      }
    }

    if (!added) {
      this.items.push(item);
    }
  }

  dequeue() {
    if (this.isEmpty()) {
      return undefined;
    }
    return this.items.shift().element;
  }

  isEmpty() {
    return this.items.length === 0;
  }
}

// Использование
const pQueue = new PriorityQueue();
pQueue.enqueue('обычная задача', 3);
pQueue.enqueue('критичная ошибка', 1);
pQueue.enqueue('важное сообщение', 2);

console.log(pQueue.dequeue()); // "критичная ошибка" (приоритет 1)
console.log(pQueue.dequeue()); // "важное сообщение" (приоритет 2)
console.log(pQueue.dequeue()); // "обычная задача" (приоритет 3)

Очередь для обработки API запросов

class RequestQueue {
  constructor(maxRetries = 3) {
    this.queue = [];
    this.processing = false;
    this.maxRetries = maxRetries;
  }

  add(url, options = {}) {
    return new Promise((resolve, reject) => {
      this.queue.push({
        url,
        options,
        resolve,
        reject,
        retries: 0
      });
      this.process();
    });
  }

  async process() {
    if (this.processing || this.queue.length === 0) {
      return;
    }

    this.processing = true;
    const request = this.queue.shift();

    try {
      const response = await fetch(request.url, request.options);

      if (!response.ok && response.status >= 500) {
        throw new Error(`Server error: ${response.status}`);
      }

      const data = await response.json();
      request.resolve(data);
    } catch (error) {
      if (request.retries < this.maxRetries) {
        request.retries++;
        // Добавить обратно в очередь для повтора
        this.queue.unshift(request);
      } else {
        request.reject(error);
      }
    } finally {
      this.processing = false;
      // Обработать следующий запрос
      setTimeout(() => this.process(), 100);
    }
  }
}

// Использование
const requestQueue = new RequestQueue(3);

requestQueue.add('/api/v1/data')
  .then(data => console.log('Данные:', data))
  .catch(error => console.error('Ошибка:', error));

Событийная очередь для React

class EventQueue {
  constructor() {
    this.listeners = {};
  }

  on(event, callback) {
    if (!this.listeners[event]) {
      this.listeners[event] = [];
    }
    this.listeners[event].push(callback);
  }

  off(event, callback) {
    if (!this.listeners[event]) return;
    this.listeners[event] = this.listeners[event].filter(cb => cb !== callback);
  }

  emit(event, data) {
    if (!this.listeners[event]) return;
    this.listeners[event].forEach(callback => callback(data));
  }
}

// Использование в React
import { useEffect } from 'react';

const eventQueue = new EventQueue();

export function Component() {
  useEffect(() => {
    const handleUpdate = (data) => {
      console.log('Данные обновлены:', data);
    };

    eventQueue.on('update', handleUpdate);

    return () => {
      eventQueue.off('update', handleUpdate);
    };
  }, []);

  const triggerUpdate = () => {
    eventQueue.emit('update', { newData: 'example' });
  };

  return <button onClick={triggerUpdate}>Обновить</button>;
}

Использование с Redux для управления состоянием

// Redux слайс для очереди задач
import { createSlice } from '@reduxjs/toolkit';

const taskQueueSlice = createSlice({
  name: 'taskQueue',
  initialState: {
    tasks: [],
    processing: false
  },
  reducers: {
    addTask: (state, action) => {
      state.tasks.push(action.payload);
    },
    removeTask: (state) => {
      state.tasks.shift();
    },
    setProcessing: (state, action) => {
      state.processing = action.payload;
    }
  }
});

export const { addTask, removeTask, setProcessing } = taskQueueSlice.actions;

Очередь - это фундаментальный паттерн для управления асинхронностью и загруженностью системы. Правильная реализация улучшает performance и UX приложения.

Как реализуешь очередь? | PrepBro