import EventEmitter from "events" const isNumber = x => typeof x === 'number' && !isNaN(x) const delay = ms => isNumber(ms) && new Promise(resolve => setTimeout(resolve, ms)) const QUEQUE_DELAY = 5 * 1000 export default class Queque extends EventEmitter { _queque = new Set() constructor() { super() } add(item) { this._queque.add(item) // console.debug('add item to queque', item, 'in index', this._queque.size) } has(item) { return this._queque.has(item) } delete(item) { this._queque.delete(item) // console.debug('delete item from queque', item, 'now have', this._queque.size, 'in queque') } first() { return [...this._queque].shift() } isFirst(item) { return this.first() === item } last() { return [...this._queque].pop() } isLast(item) { return this.last() === item } getIndex(item) { return [...this._queque].indexOf(item) } getSize() { return this._queque.size } isEmpty() { return this.getSize() === 0 } unqueue(item) { let queque; if (item) { if (this.has(item)) { queque = item const isFirst = this.isFirst(item) if (!isFirst) { throw new Error('Item is not first in queque') } } else { // console.error('try to unqueue item', item, 'but not found') } } else { queque = this.first() } if (queque) { this.delete(queque) this.emit(queque) } } waitQueue(item) { return new Promise((resolve, reject) => { // console.debug('wait queque', item) if (this.has(item)) { const solve = async (removeQueque = false) => { await delay(QUEQUE_DELAY) // console.debug('wait queque', item, 'done!') if (removeQueque) this.unqueue(item) if (!this.isEmpty()) this.unqueue() resolve() } if (this.isFirst(item)) { // console.debug('wait queque', item, 'is first in queque') solve(true) } else this.once(item, solve) } else { reject(new Error('item not found')) } }) } }