New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

pendings

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pendings - npm Package Compare versions

Comparing version 0.2.6 to 0.2.7

lib/utils.js

110

lib/pending.js

@@ -13,9 +13,29 @@ /**

var _require = require('./utils'),
mergeOptions = _require.mergeOptions;
var AUTO_RESET = {
NEVER: 'never',
FULFILLED: 'fulfilled',
RESOLVED: 'resolved',
REJECTED: 'rejected'
};
var DEFAULT_OPTIONS = {
timeout: 0,
autoReset: AUTO_RESET.NEVER
};
var Pending = function () {
/**
* Creates instance of single pending promise. It holds `resolve / reject` callbacks for future fulfillment.
* @param {Object} [options]
* @param {Number} [options.timeout=0]
* @param {String} [options.autoReset='never'] automatically reset pending to initial state.
* Possible values are: `never`, `fufilled`, `resolved`, `rejected`.
*/
function Pending() {
function Pending(options) {
_classCallCheck(this, Pending);
this._options = mergeOptions(DEFAULT_OPTIONS, options);
this._resolve = null;

@@ -49,10 +69,11 @@ this._reject = null;

* will return the same promise, which can be still pending or already fulfilled.
* To reset this behavior use `.reset()`. If `timeout` is specified, the promise will be automatically rejected
* after `timeout` milliseconds with `PendingTimeoutError`.
* To reset this behavior use `.reset()`. If `options.timeout` is specified, the promise will be automatically
* rejected after `timeout` milliseconds with `TimeoutError`.
*
* @param {Function} fn
* @param {Number} [timeout=0]
* @param {Object} [options]
* @param {Number} [options.timeout=0] timeout after which promise will be automatically rejected
* @returns {Promise}
*/
value: function call(fn, timeout) {
value: function call(fn, options) {
if (this._isPending || this.isFulfilled) {

@@ -62,3 +83,5 @@ return this._promise;

this.reset();
this._createPromise(fn, timeout);
this._callOptions = mergeOptions(this._options, options);
this._initPromise(fn);
this._initTimer();
return this._promise;

@@ -78,8 +101,7 @@ }

if (this._isPending) {
this._isPending = false;
this._preFulfill();
this._isResolved = true;
this._value = value;
this._clearTimer();
this._resolve(value);
this._onFulfilled(this);
this._postFulfill();
}

@@ -98,8 +120,7 @@ }

if (this._isPending) {
this._isPending = false;
this._preFulfill();
this._isRejected = true;
this._value = value;
this._clearTimer();
this._reject(value);
this._onFulfilled(this);
this._postFulfill();
}

@@ -146,10 +167,2 @@ }

}, {
key: '_createPromise',
value: function _createPromise(fn, timeout) {
this._initPromise(fn);
if (timeout) {
this._initTimer(timeout);
}
}
}, {
key: '_initPromise',

@@ -169,19 +182,12 @@ value: function _initPromise(fn) {

}, {
key: '_callFn',
value: function _callFn(fn) {
try {
var res = fn();
this._proxyPromise(res);
} catch (e) {
this.reject(e);
}
}
}, {
key: '_initTimer',
value: function _initTimer(timeout) {
value: function _initTimer() {
var _this2 = this;
this._timer = setTimeout(function () {
return _this2.reject(new TimeoutError(timeout));
}, timeout);
var timeout = this._callOptions.timeout;
if (timeout) {
this._timer = setTimeout(function () {
return _this2.reject(new TimeoutError(timeout));
}, timeout);
}
}

@@ -197,4 +203,14 @@ }, {

}, {
key: '_proxyPromise',
value: function _proxyPromise(p) {
key: '_callFn',
value: function _callFn(fn) {
try {
var res = fn();
this._attachToFnPromise(res);
} catch (e) {
this.reject(e);
}
}
}, {
key: '_attachToFnPromise',
value: function _attachToFnPromise(p) {
var _this3 = this;

@@ -211,2 +227,24 @@

}, {
key: '_preFulfill',
value: function _preFulfill() {
this._isPending = false;
this._clearTimer();
}
}, {
key: '_postFulfill',
value: function _postFulfill() {
this._onFulfilled(this);
this._applyAutoReset();
}
}, {
key: '_applyAutoReset',
value: function _applyAutoReset() {
var autoReset = this._options.autoReset;
var needReset = [autoReset === AUTO_RESET.FULFILLED, this._isResolved && autoReset === AUTO_RESET.RESOLVED, this._isRejected && autoReset === AUTO_RESET.REJECTED].some(Boolean);
if (needReset) {
this.reset();
}
}
}, {
key: 'promise',

@@ -213,0 +251,0 @@ get: function get() {

@@ -13,2 +13,5 @@ /**

var _require = require('./utils'),
mergeOptions = _require.mergeOptions;
var DEFAULT_OPTIONS = {

@@ -22,8 +25,8 @@ autoRemove: false,

/**
* Creates dynamic list of promises. When each promise if fulfilled it is remove from list.
* Manipulation of list of promises.
*
* @param {Object} [options]
* @param {Number} [options.autoRemove=false] automatically remove fulfilled promises
* @param {Number} [options.autoRemove=false] automatically remove fulfilled promises from list
* @param {Number} [options.timeout=0] default timeout for all promises
* @param {String} [options.idPrefix=''] prefix for generated IDs
* @param {String} [options.idPrefix=''] prefix for generated promise IDs
*/

@@ -33,5 +36,5 @@ function Pendings(options) {

this._options = Object.assign({}, DEFAULT_OPTIONS, options);
this._options = mergeOptions(DEFAULT_OPTIONS, options);
this._map = Object.create(null);
this._waitingAll = new Pending();
this._waitingAll = new Pending({ autoReset: 'never' });
}

@@ -70,3 +73,3 @@

* @param {Object} [options]
* @param {Number} [options.timeout] custom timeout for particular promise
* @param {Number} [options.timeout=0] custom timeout for particular promise
* @returns {Promise}

@@ -83,4 +86,6 @@ */

} else {
var pending = this._map[id] = new Pending();
var timeout = this._getTimeout(options);
var _mergeOptions = mergeOptions(this._options, options),
timeout = _mergeOptions.timeout;
var pending = this._map[id] = new Pending({ timeout: timeout });
pending.onFulfilled = function () {

@@ -91,3 +96,3 @@ return _this._onFulfilled(id);

return fn(id);
}, timeout);
});
}

@@ -229,3 +234,3 @@ }

*
* @returns {Promise} promise resolved with `{resolved: <Array>, rejected: <Array>}`
* @returns {Promise} promise resolved with object `{resolved: {id: value, ...}, rejected: {id: value, ...}}`
*/

@@ -232,0 +237,0 @@

{
"name": "pendings",
"version": "0.2.6",
"version": "0.2.7",
"description": "Better control of promises",

@@ -5,0 +5,0 @@ "author": {

@@ -7,6 +7,6 @@ # Pendings

> Better control of [Promises](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise)
> Better control of [Promises]
*Pendings* is a library for more flexible control over promises. It is useful in event-based code
where you need to manually store `resolve` / `reject` callbacks for later fulfillment.
*Pendings* is a wrapping library over [Promises] providing flexible control of promise lifecycle.
It is useful for event-based code where you need to manually store `resolve` / `reject` callbacks for later fulfillment.
It reduces boilerplate code and allows to split business logic from promise manipulation.

@@ -19,2 +19,8 @@

## Features
* automatically store `resolve` / `reject` callbacks for later fulfillment
* automatically return existing promise for all calls until promise is fulfilled
* automatic reject promise after configured `timeout`
* flexible manipulation with list of promises: dynamic insert and `waitAll()` method
## Usage (single promise)

@@ -94,1 +100,3 @@ Typical situation with promises in event-based code:

MIT @ [Vitaliy Potapov](https://github.com/vitalets)
[Promises]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise

@@ -7,6 +7,6 @@ # Pendings

> Better control of [Promises](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise)
> Better control of [Promises]
*Pendings* is a library for more flexible control over promises. It is useful in event-based code
where you need to manually store `resolve` / `reject` callbacks for later fulfillment.
*Pendings* is a wrapping library over [Promises] providing flexible control of promise lifecycle.
It is useful for event-based code where you need to manually store `resolve` / `reject` callbacks for later fulfillment.
It reduces boilerplate code and allows to split business logic from promise manipulation.

@@ -19,2 +19,8 @@

## Features
* automatically store `resolve` / `reject` callbacks for later fulfillment
* automatically return existing promise for all calls until promise is fulfilled
* automatic reject promise after configured `timeout`
* flexible manipulation with list of promises: dynamic insert and `waitAll()` method
## Usage (single promise)

@@ -107,3 +113,3 @@ Typical situation with promises in event-based code:

* [Pending](#Pending)
* [new Pending()](#new_Pending_new)
* [new Pending([options])](#new_Pending_new)
* [.promise](#Pending+promise) ⇒ <code>Promise</code>

@@ -116,3 +122,3 @@ * [.value](#Pending+value) ⇒ <code>\*</code>

* [.onFulfilled](#Pending+onFulfilled)
* [.call(fn, [timeout])](#Pending+call) ⇒ <code>Promise</code>
* [.call(fn, [options])](#Pending+call) ⇒ <code>Promise</code>
* [.resolve([value])](#Pending+resolve)

@@ -125,5 +131,12 @@ * [.reject([value])](#Pending+reject)

### new Pending()
### new Pending([options])
Creates instance of single pending promise. It holds `resolve / reject` callbacks for future fulfillment.
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| [options] | <code>Object</code> | | |
| [options.timeout] | <code>Number</code> | <code>0</code> | |
| [options.autoReset] | <code>String</code> | <code>&#x27;never&#x27;</code> | automatically reset pending to initial state. Possible values are: `never`, `fufilled`, `resolved`, `rejected`. |
<a name="Pending+promise"></a>

@@ -178,15 +191,16 @@

### pending.call(fn, [timeout]) ⇒ <code>Promise</code>
### pending.call(fn, [options]) ⇒ <code>Promise</code>
For the first time this method calls `fn` and returns new promise. Also holds `resolve` / `reject` callbacks
to allow fulfill promise via `pending.resolve()` and `pending.reject()`. All subsequent calls of `.call(fn)`
will return the same promise, which can be still pending or already fulfilled.
To reset this behavior use `.reset()`. If `timeout` is specified, the promise will be automatically rejected
after `timeout` milliseconds with `PendingTimeoutError`.
To reset this behavior use `.reset()`. If `options.timeout` is specified, the promise will be automatically
rejected after `timeout` milliseconds with `TimeoutError`.
**Kind**: instance method of [<code>Pending</code>](#Pending)
| Param | Type | Default |
| --- | --- | --- |
| fn | <code>function</code> | |
| [timeout] | <code>Number</code> | <code>0</code> |
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| fn | <code>function</code> | | |
| [options] | <code>Object</code> | | |
| [options.timeout] | <code>Number</code> | <code>0</code> | timeout after which promise will be automatically rejected |

@@ -263,3 +277,3 @@ <a name="Pending+resolve"></a>

### new Pendings([options])
Creates dynamic list of promises. When each promise if fulfilled it is remove from list.
Manipulation of list of promises.

@@ -270,5 +284,5 @@

| [options] | <code>Object</code> | | |
| [options.autoRemove] | <code>Number</code> | <code>false</code> | automatically remove fulfilled promises |
| [options.autoRemove] | <code>Number</code> | <code>false</code> | automatically remove fulfilled promises from list |
| [options.timeout] | <code>Number</code> | <code>0</code> | default timeout for all promises |
| [options.idPrefix] | <code>String</code> | <code>&#x27;&#x27;</code> | prefix for generated IDs |
| [options.idPrefix] | <code>String</code> | <code>&#x27;&#x27;</code> | prefix for generated promise IDs |

@@ -302,8 +316,8 @@ <a name="Pendings+count"></a>

| Param | Type | Description |
| --- | --- | --- |
| id | <code>String</code> | |
| fn | <code>function</code> | |
| [options] | <code>Object</code> | |
| [options.timeout] | <code>Number</code> | custom timeout for particular promise |
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| id | <code>String</code> | | |
| fn | <code>function</code> | | |
| [options] | <code>Object</code> | | |
| [options.timeout] | <code>Number</code> | <code>0</code> | custom timeout for particular promise |

@@ -415,3 +429,3 @@ <a name="Pendings+has"></a>

**Kind**: instance method of [<code>Pendings</code>](#Pendings)
**Returns**: <code>Promise</code> - promise resolved with `{resolved: <Array>, rejected: <Array>}`
**Returns**: <code>Promise</code> - promise resolved with object `{resolved: {id: value, ...}, rejected: {id: value, ...}}`
<a name="Pendings+clear"></a>

@@ -447,1 +461,3 @@

MIT @ [Vitaliy Potapov](https://github.com/vitalets)
[Promises]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise

@@ -8,8 +8,26 @@ /**

const TimeoutError = require('./timeout-error');
const {mergeOptions} = require('./utils');
const AUTO_RESET = {
NEVER: 'never',
FULFILLED: 'fulfilled',
RESOLVED: 'resolved',
REJECTED: 'rejected',
};
const DEFAULT_OPTIONS = {
timeout: 0,
autoReset: AUTO_RESET.NEVER,
};
class Pending {
/**
* Creates instance of single pending promise. It holds `resolve / reject` callbacks for future fulfillment.
* @param {Object} [options]
* @param {Number} [options.timeout=0]
* @param {String} [options.autoReset='never'] automatically reset pending to initial state.
* Possible values are: `never`, `fufilled`, `resolved`, `rejected`.
*/
constructor() {
constructor(options) {
this._options = mergeOptions(DEFAULT_OPTIONS, options);
this._resolve = null;

@@ -99,10 +117,11 @@ this._reject = null;

* will return the same promise, which can be still pending or already fulfilled.
* To reset this behavior use `.reset()`. If `timeout` is specified, the promise will be automatically rejected
* after `timeout` milliseconds with `PendingTimeoutError`.
* To reset this behavior use `.reset()`. If `options.timeout` is specified, the promise will be automatically
* rejected after `timeout` milliseconds with `TimeoutError`.
*
* @param {Function} fn
* @param {Number} [timeout=0]
* @param {Object} [options]
* @param {Number} [options.timeout=0] timeout after which promise will be automatically rejected
* @returns {Promise}
*/
call(fn, timeout) {
call(fn, options) {
if (this._isPending || this.isFulfilled) {

@@ -112,3 +131,5 @@ return this._promise;

this.reset();
this._createPromise(fn, timeout);
this._callOptions = mergeOptions(this._options, options);
this._initPromise(fn);
this._initTimer();
return this._promise;

@@ -125,8 +146,7 @@ }

if (this._isPending) {
this._isPending = false;
this._preFulfill();
this._isResolved = true;
this._value = value;
this._clearTimer();
this._resolve(value);
this._onFulfilled(this);
this._postFulfill();
}

@@ -142,8 +162,7 @@ }

if (this._isPending) {
this._isPending = false;
this._preFulfill();
this._isRejected = true;
this._value = value;
this._clearTimer();
this._reject(value);
this._onFulfilled(this);
this._postFulfill();
}

@@ -184,9 +203,2 @@ }

_createPromise(fn, timeout) {
this._initPromise(fn);
if (timeout) {
this._initTimer(timeout);
}
}
_initPromise(fn) {

@@ -203,15 +215,9 @@ this._promise = new Promise((resolve, reject) => {

_callFn(fn) {
try {
const res = fn();
this._proxyPromise(res);
} catch (e) {
this.reject(e);
_initTimer() {
const timeout = this._callOptions.timeout;
if (timeout) {
this._timer = setTimeout(() => this.reject(new TimeoutError(timeout)), timeout);
}
}
_initTimer(timeout) {
this._timer = setTimeout(() => this.reject(new TimeoutError(timeout)), timeout);
}
_clearTimer() {

@@ -224,3 +230,12 @@ if (this._timer) {

_proxyPromise(p) {
_callFn(fn) {
try {
const res = fn();
this._attachToFnPromise(res);
} catch (e) {
this.reject(e);
}
}
_attachToFnPromise(p) {
if (p && typeof p.then === 'function') {

@@ -230,4 +245,26 @@ p.then(value => this.resolve(value), e => this.reject(e));

}
_preFulfill() {
this._isPending = false;
this._clearTimer();
}
_postFulfill() {
this._onFulfilled(this);
this._applyAutoReset();
}
_applyAutoReset() {
const {autoReset} = this._options;
const needReset = [
autoReset === AUTO_RESET.FULFILLED,
this._isResolved && autoReset === AUTO_RESET.RESOLVED,
this._isRejected && autoReset === AUTO_RESET.REJECTED
].some(Boolean);
if (needReset) {
this.reset();
}
}
}
module.exports = Pending;

@@ -8,2 +8,3 @@ /**

const Pending = require('./pending');
const {mergeOptions} = require('./utils');

@@ -18,13 +19,13 @@ const DEFAULT_OPTIONS = {

/**
* Creates dynamic list of promises. When each promise if fulfilled it is remove from list.
* Manipulation of list of promises.
*
* @param {Object} [options]
* @param {Number} [options.autoRemove=false] automatically remove fulfilled promises
* @param {Number} [options.autoRemove=false] automatically remove fulfilled promises from list
* @param {Number} [options.timeout=0] default timeout for all promises
* @param {String} [options.idPrefix=''] prefix for generated IDs
* @param {String} [options.idPrefix=''] prefix for generated promise IDs
*/
constructor(options) {
this._options = Object.assign({}, DEFAULT_OPTIONS, options);
this._options = mergeOptions(DEFAULT_OPTIONS, options);
this._map = Object.create(null);
this._waitingAll = new Pending();
this._waitingAll = new Pending({autoReset: 'never'});
}

@@ -61,3 +62,3 @@

* @param {Object} [options]
* @param {Number} [options.timeout] custom timeout for particular promise
* @param {Number} [options.timeout=0] custom timeout for particular promise
* @returns {Promise}

@@ -69,6 +70,6 @@ */

} else {
const pending = this._map[id] = new Pending();
const timeout = this._getTimeout(options);
const {timeout} = mergeOptions(this._options, options);
const pending = this._map[id] = new Pending({timeout});
pending.onFulfilled = () => this._onFulfilled(id);
return pending.call(() => fn(id), timeout);
return pending.call(() => fn(id));
}

@@ -182,3 +183,3 @@ }

*
* @returns {Promise} promise resolved with `{resolved: <Array>, rejected: <Array>}`
* @returns {Promise} promise resolved with object `{resolved: {id: value, ...}, rejected: {id: value, ...}}`
*/

@@ -185,0 +186,0 @@ waitAll() {

@@ -263,5 +263,6 @@ 'use strict';

describe('timeout', function () {
describe('constructor options: timeout', function () {
it('should resolve before timeout', function () {
const res = this.pending.call(noop, 10);
this.pending = new Pending({timeout: 10});
const res = this.pending.call(noop);
setTimeout(() => this.pending.resolve('foo'), 5);

@@ -272,3 +273,4 @@ return assert.eventually.equal(res, 'foo');

it('should reject after timeout', function () {
const res = this.pending.call(noop, 10);
this.pending = new Pending({timeout: 10});
const res = this.pending.call(noop);
setTimeout(() => this.pending.resolve('foo'), 20);

@@ -278,2 +280,101 @@ return assert.isRejected(res, 'Promise rejected by timeout (10 ms)');

});
describe('call options: timeout', function () {
it('should resolve before timeout', function () {
const res = this.pending.call(noop, {timeout: 10});
setTimeout(() => this.pending.resolve('foo'), 5);
return assert.eventually.equal(res, 'foo');
});
it('should reject after timeout', function () {
const res = this.pending.call(noop, {timeout: 10});
setTimeout(() => this.pending.resolve('foo'), 20);
return assert.isRejected(res, 'Promise rejected by timeout (10 ms)');
});
it('should overwrite default timeout', function () {
this.pending = new Pending({timeout: 10});
const res = this.pending.call(noop, {timeout: 20});
setTimeout(() => this.pending.resolve('foo'), 15);
return assert.eventually.equal(res, 'foo');
});
it('should not overwrite default timeout with undefined', function () {
this.pending = new Pending({timeout: 10});
const res = this.pending.call(noop, {timeout: undefined});
setTimeout(() => this.pending.resolve('foo'), 5);
return assert.eventually.equal(res, 'foo');
});
});
describe('constructor options: autoReset', function () {
describe('never', function () {
it('should keep promise on next calls after resolve', function () {
this.pending = new Pending({autoReset: 'never'});
const p = this.pending.call();
this.pending.resolve();
assert.equal(p, this.pending.call());
});
it('should keep promise on next calls after reject', function () {
this.pending = new Pending({autoReset: 'never'});
const p = this.pending.call();
p.catch(() => {});
this.pending.reject();
assert.equal(p, this.pending.call());
});
});
describe('resolved', function () {
it('should not keep promise on next calls after resolve', function () {
this.pending = new Pending({autoReset: 'resolved'});
const p = this.pending.call();
this.pending.resolve();
assert.notEqual(p, this.pending.call());
});
it('should keep promise on next calls after reject', function () {
this.pending = new Pending({autoReset: 'resolved'});
const p = this.pending.call();
p.catch(() => {});
this.pending.reject();
assert.equal(p, this.pending.call());
});
});
describe('rejected', function () {
it('should keep promise on next calls after resolve', function () {
this.pending = new Pending({autoReset: 'rejected'});
const p = this.pending.call();
this.pending.resolve();
assert.equal(p, this.pending.call());
});
it('should not keep promise on next calls after reject', function () {
this.pending = new Pending({autoReset: 'rejected'});
const p = this.pending.call();
p.catch(() => {});
this.pending.reject();
assert.notEqual(p, this.pending.call());
});
});
describe('fulfilled', function () {
it('should not keep promise on next calls after resolve', function () {
this.pending = new Pending({autoReset: 'fulfilled'});
const p = this.pending.call();
this.pending.resolve();
assert.notEqual(p, this.pending.call());
});
it('should not keep promise on next calls after reject', function () {
this.pending = new Pending({autoReset: 'fulfilled'});
const p = this.pending.call();
p.catch(() => {});
this.pending.reject();
assert.notEqual(p, this.pending.call());
});
});
});
});

@@ -160,2 +160,3 @@ 'use strict';

const res = pendings.set(1, noop, {timeout: 5});
res.catch(() => {});
return wait(10).then(() => assert.isRejected(res, 'Promise rejected by timeout (5 ms)'));

@@ -162,0 +163,0 @@ });

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc