From 5098a10bfb8b30f4adab4a93066ee93d031e0c45 Mon Sep 17 00:00:00 2001 From: Forbes Lindesay Date: Sat, 30 Jan 2021 14:28:35 +0000 Subject: [PATCH] type definitions, faster queue, rename pop to shift BREAKING CHANGES: - `pop` is renamed to `shift` to better align with queue behaviour, `pop` implies a stack - the queue is no longer an event emitter as that creates some unnecessary performance overhead and makes this library harder to use in a browser - requires a native Promise implementation --- README.md | 13 ++++------- index.d.ts | 6 +++++ index.js | 64 +++++++++++++++++++++++++++++++++------------------ package.json | 2 +- test/index.js | 29 +++++------------------ 5 files changed, 59 insertions(+), 55 deletions(-) create mode 100644 index.d.ts diff --git a/README.md b/README.md index c0d8f4c..557831c 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,7 @@ a simple asynchronous queue [![Build Status](https://img.shields.io/travis/then/queue/master.svg)](https://travis-ci.org/then/queue) -[![Dependency Status](https://img.shields.io/gemnasium/then/queue.svg)](https://gemnasium.com/then/queue) -[![NPM version](https://img.shields.io/npm/v/then-queue.svg)](http://badge.fury.io/js/then-queue) +[![NPM version](https://img.shields.io/npm/v/then-queue.svg)](https://www.npmjs.com/package/then-queue) ## Installation @@ -25,14 +24,10 @@ var q = new Queue(); Push an item onto the queue -### queue.pop() -> Promise Item +### queue.shift() -> Promise Item - Pop an item from the queue + Remove an item from the queue ### queue.length - Amount of items in the queue (note that this can be negative if `pop` has been called more times than `push`). - -### Events - -The `length-changed` event gets emitted whenever `pop` or `push` has been called. You could use it to spawn/kill workers when the length changes. \ No newline at end of file + Amount of items in the queue (note that this can be negative if `shift` has been called more times than `push`). diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..fcbf535 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,6 @@ +declare class ThenQueue { + readonly length: number; + push(item: T | Promise): void; + shift(): Promise +} +export default ThenQueue; \ No newline at end of file diff --git a/index.js b/index.js index e770ed6..0d0eac8 100644 --- a/index.js +++ b/index.js @@ -1,24 +1,20 @@ 'use strict'; -var EventEmitter = require('events').EventEmitter -var Promise = require('promise') +module.exports = ThenQueue +module.exports.default = ThenQueue -module.exports = Queue -function Queue() { - if (!(this instanceof Queue)) return new Queue() - EventEmitter.call(this) - this._items = [] - this._waiting = [] +function ThenQueue() { + if (!(this instanceof ThenQueue)) return new ThenQueue() + this._items = new SimpleQueue(); + this._waiting = new SimpleQueue(); this.length = 0 } -Queue.prototype = Object.create(EventEmitter.prototype) -Queue.prototype.constructor = Queue -Queue.prototype.push = function(item) { +ThenQueue.prototype.push = function push(item) { this.length++ - this.emit('length-changed', this.length) - if (this._waiting.length) { - var waiting = this._waiting.shift() + + var waiting = this._waiting.shift() + if (waiting) { waiting(item) } else { @@ -26,16 +22,40 @@ Queue.prototype.push = function(item) { } } -Queue.prototype.pop = function(cb) { var self = this +ThenQueue.prototype.shift = function shift() { this.length-- - this.emit('length-changed', this.length) - if (this._items.length) { - var item = this._items.shift() - return Promise.resolve(item).nodeify(cb) + + var item = this._items.shift() + if (item) { + return Promise.resolve(item) } else { - return new Promise(function(resolve, reject) { - self._waiting.push(resolve) - }).nodeify(cb) + var waiting = this._waiting + return new Promise(function(resolve) { + waiting.push(resolve) + }) + } +} + +function SimpleQueue() { + this._head = []; + this._tail = []; +} +SimpleQueue.prototype.push = function push(item) { + this._tail.push(item); +} +SimpleQueue.prototype.shift = function shift() { + if (this._head.length !== 0) { + return this._head.pop(); + } + if (this._tail.length === 1) { + return this._tail.pop(); + } + if (this._tail.length > 1) { + var temp = this._tail.reverse() + this._tail = this._head + this._head = temp + return this._head.pop(); } + return undefined; } diff --git a/package.json b/package.json index 772d539..fdcce15 100644 --- a/package.json +++ b/package.json @@ -27,4 +27,4 @@ "scripts": { "test": "node test" } -} \ No newline at end of file +} diff --git a/test/index.js b/test/index.js index 768791e..04bf20f 100644 --- a/test/index.js +++ b/test/index.js @@ -6,46 +6,31 @@ var Queue = require('../') test('queue', function () { var q = new Queue(); - var length = 0; var results = []; - q.on('length-changed', function (l) { - assert(q.length === l) - assert(length !== l) - length = l - }) assert(q.length === 0); q.push(1); assert(q.length === 1); - assert(length === 1); q.push(2); assert(q.length === 2); - assert(length === 2); q.push(3); assert(q.length === 3); - assert(length === 3); - return q.pop().then(function (n) { + return q.shift().then(function (n) { assert(n === 1); assert(q.length === 2); - assert(length === 2); - return q.pop(); + return q.shift(); }).then(function (n) { assert(n === 2); assert(q.length === 1); - assert(length === 1); - return q.pop(); + return q.shift(); }).then(function (n) { assert(n === 3); assert(q.length === 0); - assert(length === 0); - results.push(q.pop()); + results.push(q.shift()); assert(q.length === -1); - assert(length === -1); - results.push(q.pop()); + results.push(q.shift()); assert(q.length === -2); - assert(length === -2); - results.push(q.pop()); + results.push(q.shift()); assert(q.length === -3); - assert(length === -3); q.push(1); assert(q.length === -2); return results.shift(); @@ -53,13 +38,11 @@ test('queue', function () { assert(n === 1); q.push(2); assert(q.length === -1); - assert(length === -1); return results.shift(); }).then(function (n) { assert(n === 2); q.push(3); assert(q.length === 0); - assert(length === 0); return results.shift(); }).then(function (n) { assert(n === 3);