Асинхронные Очереди


реализован базовый асинхронный очереди так, что я могу сделать

await queue.push(item);
const item = await queue.pop();

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

class Queue {
  constructor() {
    this.dict = {};
    this.start = 0;
    this.end = 0;
  }

  /**
   *
   * todo: if the number of operations exceed Number.MAX_SAFE_INTEGER (~ 2**53)
   * todo: there will be overflow errors, so shift the elements
   * todo: and make the operations asymptotically O(1)
   *
   * @param {*} item
   */
  push (item) {
    this.dict[this.end] = item;
    this.end += 1;
  }

  get length() {
    return this.end - this.start;
  }

  /**
   *
   * @returns {*}
   */
  pop () {
    if (this.start === this.end) {
      throw "OutOfBounds Exception, can't pop from an empty queue";
    }
    const item = this.dict[this.start];
    this.start += 1;
    return item;
  }

}


class AsyncQueue {
  constructor() {
    this.sync_queue = new Queue();
    this.waiting_minions = new Queue();
  }

  async push(item) {
    if (this.waiting_minions.length > 0) {
      const signal = this.waiting_minions.pop();
      await signal(item);
    } else {
      this.sync_queue.push(item);
    }
  }

  get length() {
    return this.sync_queue.length;
  }

  pop() {
    return new Promise((resolve) => {
      if (this.sync_queue.length > 0) {
        return resolve(this.sync_queue.pop());
      }
      this.waiting_minions.push(resolve);
    });
  }

}

module.exports = AsyncQueue;


Комментарии
2 ответа


  • Queue: есть причина, почему вы вручную использовать смещение внутри массива вместо Array#push() и Array#shift()?
    Я не знаю внутренней реализации их в системах JS, но я бы их использовать без профилирования может поступить иначе.

  • AsyncQueue#pop():


    • Объявить его как async, даже если вы не пользуетесь awaitон будет служить читаемость.

    • Предпочитаете ли-еще более ранняя return (в этой конкретной ситуации). Особенно, return resolve(...) похоже, вас ожидает возвращаемое значение resolve (это не обязательно одно насколько мне известно), но вы на самом деле только с помощью return для контроля потока управления.

      async pop() {
      return new Promise(resolve => {
      if (this.sync_queue.length > 0) {
      resolve(this.sync_queue.pop());
      }
      else {
      this.waiting_minions.push(resolve);
      }
      });
      }


  • AsyncQueue#push(): вы используете его async? В случае, если нет никакого ожидания pop() операции, он сразу же решает. В случае, если он есть, он ждет вызывающий код pop() операция по полной, если я не ошибаюсь:

    setTimeout(async () => {
    await queue.pop();
    while (1);
    }, 100);

    await queue.push(42);
    // This line will never be reached


  • (Async)Queue#lengthя бы объявить его как функцию по тем же причинам, которые я изложил в другом обзоре.

  • AsyncQueue#length: this.arr не существует. Ты хотел написать this.sync_queue.length?

1
ответ дан 12 марта 2018 в 09:03 Источник Поделиться

Некоторые вопросы, черный список модуля в некоторых организациях.

Ненадежное

Все это является небезопасным из-за свойств. Свойствам должны быть защищены от неправильного использования через код, либо


  1. Ветеринары небезопасного состояния свойств перед их использованием.

  2. Прячет их так, что они не доступны.

  3. Использует сеттеры для предотвращения мутации или ненадлежащем состоянии.

Некоторые основные примеры неправильного использования после ожидаемого вызова

const aQueue = new AsyncQueue();  // invocation 

Любое одно из следующих действий делает состояние непригодным или ошибочное

aQueue.sync_queue = new AsyncQueue();
aQueue.sync_queue.push("monkey");
aQueue.sync_queue.start = "0"; // start will concat rather than add 1
aQueue.sync_queue.start = 2; // pop untrusted
aQueue.sync_queue.end = -1; // push can overwrite queue items
aQueue.sync_queue.dict = null; // complete destruction
// and many other ways

Нечистый

Вы не почтительно выскочил предметы в силу создания псевдо-утечка памяти. Длительный срок использования экземпляра AsyncQueue будет представлять собой унижающее достоинство обслуживания, что в конечном итоге аварии узла связи с Out of memory ошибка

Двусмысленность

Вы бросаете исключение, что означает, что вы ожидаете Queue чтобы использоваться независимо от AsyncQueue интерфейс. AsyncQueue никогда не поп sync_queue если его length равна нулю, так зачем бросать?

Но если Queue'ы интерфейс используется почему главный интерфейс не защищен от разрегулированных очереди?

Небезопасно выбрасывать

Вы не должны бросить.

undefined принимаем возвращение для поп-функций на пустой список / очередь / массив / и т. д... в JS. Метания-это крайняя мера, когда нет другого пути для защиты государственной приложение. Вы не можете знать, если поп на пустой очереди будет повредить, используя государственные объекты, так что вы не должны бросать ошибку как что куда более вероятно, чтобы нанести ущерб.

Летний

Этот обзор является жесткой, и это в первую очередь аргумент против использования class для определения объекта прототипы.

В настоящее время синтаксис класса JS является неполной и нарушает парадигму ОО заключение не предоставляет механизм, чтобы скрыть инкапсулированные свойства. Вы не должны использовать class синтаксис для определения объектов, которые имеют уязвимом состоянии.

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

3
ответ дан 12 марта 2018 в 03:03 Источник Поделиться