8.5. Вспомним об очереди

Очереди мы тоже рассматривали вместе со стеком во втором разделе. Если вы помните о стеке, но забыли про концепт очереди — советуем вернуться назад и перечитать статью.

Посмотрим на ещё один пример очереди. В вебе часто требуется поставить несколько процессов в очередь на обработку. Это могут быть, например, запросы на бэкенд по клику на кнопки. Бывают такие случаи, когда перед следующим запросом нужно дождаться выполнения предыдущего. Это может быть и удаление из списка взаимосвязанных элементов: нам нужно дождаться удаления элемента и всех его зависимостей перед тем, как разрешить пользователю удалять другой элемент. Вдруг он пробует удалить уже несуществующий после предыдущей операции элемент.

Такие задачи очень просто реализуется очередью. Если мы вызываем функцию, а она ещё не закончила своё выполнение, то мы кладём её вызов в очередь с push. А как только предыдущая задача выполнится — сделаем shift и выполним следующую по очереди задачу.

Queue

Очередь запросов

Можно написать функцию, которая позволит оборачивать в очередь любую функцию, возвращающую промис:

function createQueue(asyncFunction) {
  // Создаём нашу очередь, будем хранить в ней аргументы для функции
  const queue = [];

  function dequeue() {
    // Берём аргументы из начала массива и вызываем функцию
    const args = queue[0];

    asyncFunction(...args).then(() => {
      // Как только промис нашей функции выполнится, удаляем выполнение этого задания из очереди
      queue.shift();

      // А если в очереди что-то осталось — выполняем
      if (queue.length) {
        dequeue();
      }
    })
  }

  // Вызываем функцию, обёрнутую в очередь, как обычно
  return (...args) => {
    // Кладём в очередь аргументы, необходимые для выполнения
    queue.push(args);

    // Если в очереди есть только наша задача — берём и выполняем её
    if (queue.length === 1) {
      dequeue();
    }
  }
}