Описание проблемы

Реализуйте функцию дозатора JavaScript, она должна возвращать объект двумя методами: «добавить» и «удалить».

«добавить» должен добавить задачу в очередь и запустить задачи в очереди пакетами указанного размера.

«удалить» должно удалить задачу из очереди

Дозатор проверяет, есть ли запущенные задачи, если нет, то запускает задачи в очереди до тех пор, пока очередь не опустеет.

Задача определяется как функция, которая возвращает обещание.

Выполнение

Вы можете проверить этот репозиторий github: jinxuan/js-batcher (github.com)

Структура данных

Для начала нам нужно определить основную структуру данных.

Нам нужна карта задач, где ключ — это уникальное целое число, значение идентификатора — это задача.

Нам также нужен связанный список/очередь

function batcher(batchSize = 10) {
  let taskMap = {};
  let runnningTasks = {]
  let running = false;
  let nextId = 0;
  let head = {id: null, next: null};
  let tail = head;
}

Удалить API

 remove(id) {
    if (!taskMap[id]) return;
    const node = taskMap[id];
    if (!runningTasks[id]) node.reject('Batcher task aborted');
    delete taskMap[id];
    Object.assign(node, node.next);
    if (node.id) taskMap[node.id] = node;
    else tail = node;
},

Добавить API

add(task) {
          const id = nextId();
          console.log('batcher add task', id);
          const promise = new Promise((resolve, reject) => taskMap[id] = Object.assign(tail, { id, task, resolve, reject }));
          taskMap[id].next = tail = newTail();
          if (!running) {
              (async() => {
                  running = true;
                  while (head.next) {
                      while (Object.values(runningTasks).length >= batchSize) await Promise.race(Object.values(runningTasks));
                      const { id, task, resolve, reject } = head;
                      runningTasks[id] = (async() => {
                          try {
                              resolve(await task());
                          } catch (e) {
                              reject(e);
                          } finally {
                              delete runningTasks[id];
                          }
                      })();
                      console.log('Finish running task ', id);
                      this.remove(id);
                  }
                  running = false;
              })();
          }
          return { id, promise };
      }
  };

Улучшение

Добавьте другой API для отмены запроса

Ссылка:

javascript — Понимание использования promise.race () — Stack Overflow