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.3 to 0.2.4

66

lib/pending.js

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

this._isRejected = false;
this._value = undefined;
this._promise = null;

@@ -77,2 +78,3 @@ this._timer = null;

this._isResolved = true;
this._value = value;
this._clearTimer();

@@ -85,5 +87,5 @@ this._resolve(value);

/**
* Rejects pending promise with specified `reason`.
* Rejects pending promise with specified `value`.
*
* @param {*} [reason]
* @param {*} [value]
*/

@@ -93,8 +95,9 @@

key: 'reject',
value: function reject(reason) {
value: function reject(value) {
if (this._isPending) {
this._isPending = false;
this._isRejected = true;
this._value = value;
this._clearTimer();
this._reject(reason);
this._reject(value);
this._onFulfilled(this);

@@ -105,6 +108,6 @@ }

/**
* Helper method: rejects if `reason` is truthy, otherwise resolves with `value`.
* Helper method: rejects if `rejectValue` is truthy, otherwise resolves with `resolveValue`.
*
* @param {*} [value]
* @param {*} [reason]
* @param {*} [resolveValue]
* @param {*} [rejectValue]
*/

@@ -114,7 +117,7 @@

key: 'fulfill',
value: function fulfill(value, reason) {
if (reason) {
this.reject(reason);
value: function fulfill(resolveValue, rejectValue) {
if (rejectValue) {
this.reject(rejectValue);
} else {
this.resolve(value);
this.resolve(resolveValue);
}

@@ -140,2 +143,3 @@ }

this._isRejected = false;
this._value = undefined;
this._clearTimer();

@@ -169,3 +173,4 @@ }

try {
fn();
var res = fn();
this._proxyPromise(res);
} catch (e) {

@@ -193,2 +198,15 @@ this.reject(e);

}, {
key: '_proxyPromise',
value: function _proxyPromise(p) {
var _this3 = this;
if (p && typeof p.then === 'function') {
p.then(function (value) {
return _this3.resolve(value);
}, function (e) {
return _this3.reject(e);
});
}
}
}, {
key: 'promise',

@@ -200,2 +218,14 @@ get: function get() {

/**
* Returns value with that promise was fulfilled (resolved or rejected).
*
* @returns {*}
*/
}, {
key: 'value',
get: function get() {
return this._value;
}
/**
* Returns true if promise resolved.

@@ -237,2 +267,14 @@ *

/**
* Returns true if promise is pending.
*
* @returns {Boolean}
*/
}, {
key: 'isPending',
get: function get() {
return this._isPending;
}
/**
* Callback called when promise is fulfilled (resolved or rejected).

@@ -239,0 +281,0 @@ *

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

var DEFAULT_OPTIONS = {
idPrefix: '',
persistent: false,
timeout: 0
};
var Pendings = function () {

@@ -21,2 +27,3 @@ /**

* @param {Number} [options.timeout=0] default timeout for all promises
* @param {Number} [options.persistent=false] should list keep promises after fulfillment
*/

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

options = options || {};
this._timeout = options.timeout || 0;
this._idPrefix = options.idPrefix || '';
this._options = Object.assign({}, DEFAULT_OPTIONS, options);
this._map = Object.create(null);
this._waitingAll = new Pending();
}

@@ -72,3 +78,3 @@

pending.onFulfilled = function () {
return delete _this._map[id];
return _this._onFulfilled(id);
};

@@ -212,2 +218,18 @@ return pending.call(function () {

/**
* Waits for all promises to fulfill and returns object with resolved/rejected values.
*
* @returns {Promise} promise resolved with `{resolved: <Array>, rejected: <Array>}`
*/
}, {
key: 'waitAll',
value: function waitAll() {
var _this3 = this;
return this._waitingAll.call(function () {
return _this3._checkAllFulfilled();
});
}
/**
* Generates unique ID. Can be overwritten.

@@ -221,10 +243,50 @@ *

value: function generateId() {
return '' + this._idPrefix + Date.now() + '-' + Math.random();
return '' + this._options.idPrefix + Date.now() + '-' + Math.random();
}
}, {
key: '_onFulfilled',
value: function _onFulfilled(id) {
if (!this._options.persistent) {
delete this._map[id];
}
if (this._waitingAll.isPending) {
this._checkAllFulfilled();
}
}
}, {
key: '_getTimeout',
value: function _getTimeout(options) {
options = options || {};
return options.timeout !== undefined ? options.timeout : this._timeout;
return options && options.timeout !== undefined ? options.timeout : this._options.timeout;
}
}, {
key: '_checkAllFulfilled',
value: function _checkAllFulfilled() {
var _this4 = this;
var allFulfilled = Object.keys(this._map).every(function (id) {
return _this4._map[id].isFulfilled;
});
if (allFulfilled) {
var result = this._getAllValues();
this._waitingAll.resolve(result);
this._waitingAll.reset();
}
}
}, {
key: '_getAllValues',
value: function _getAllValues() {
var _this5 = this;
var resolved = {};
var rejected = {};
Object.keys(this._map).forEach(function (id) {
var pending = _this5._map[id];
if (pending.isResolved) {
resolved[id] = pending.value;
} else {
rejected[id] = pending.value;
}
});
return { resolved: resolved, rejected: rejected };
}
}]);

@@ -231,0 +293,0 @@

2

package.json
{
"name": "pendings",
"version": "0.2.3",
"version": "0.2.4",
"description": "Better control of pending promises",

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

@@ -107,11 +107,13 @@ # Pendings

* [.promise](#Pending+promise) ⇒ <code>Promise</code>
* [.value](#Pending+value) ⇒ <code>\*</code>
* [.isResolved](#Pending+isResolved) ⇒ <code>Boolean</code>
* [.isRejected](#Pending+isRejected) ⇒ <code>Boolean</code>
* [.isFulfilled](#Pending+isFulfilled) ⇒ <code>Boolean</code>
* [.isPending](#Pending+isPending) ⇒ <code>Boolean</code>
* [.onFulfilled](#Pending+onFulfilled)
* [.call(fn, [timeout])](#Pending+call) ⇒ <code>Promise</code>
* [.resolve([value])](#Pending+resolve)
* [.reject([reason])](#Pending+reject)
* [.fulfill([value], [reason])](#Pending+fulfill)
* [.reset()](#Pending+reset)
* [.reject([value])](#Pending+reject)
* [.fulfill([resolveValue], [rejectValue])](#Pending+fulfill)
* [.reset([error])](#Pending+reset)

@@ -129,2 +131,8 @@ <a name="new_Pending_new"></a>

**Kind**: instance property of [<code>Pending</code>](#Pending)
<a name="Pending+value"></a>
### pending.value ⇒ <code>\*</code>
Returns value with that promise was fulfilled (resolved or rejected).
**Kind**: instance property of [<code>Pending</code>](#Pending)
<a name="Pending+isResolved"></a>

@@ -148,2 +156,8 @@

**Kind**: instance property of [<code>Pending</code>](#Pending)
<a name="Pending+isPending"></a>
### pending.isPending ⇒ <code>Boolean</code>
Returns true if promise is pending.
**Kind**: instance property of [<code>Pending</code>](#Pending)
<a name="Pending+onFulfilled"></a>

@@ -189,4 +203,4 @@

### pending.reject([reason])
Rejects pending promise with specified `reason`.
### pending.reject([value])
Rejects pending promise with specified `value`.

@@ -197,8 +211,8 @@ **Kind**: instance method of [<code>Pending</code>](#Pending)

| --- | --- |
| [reason] | <code>\*</code> |
| [value] | <code>\*</code> |
<a name="Pending+fulfill"></a>
### pending.fulfill([value], [reason])
Helper method: rejects if `reason` is truthy, otherwise resolves with `value`.
### pending.fulfill([resolveValue], [rejectValue])
Helper method: rejects if `rejectValue` is truthy, otherwise resolves with `resolveValue`.

@@ -209,11 +223,16 @@ **Kind**: instance method of [<code>Pending</code>](#Pending)

| --- | --- |
| [value] | <code>\*</code> |
| [reason] | <code>\*</code> |
| [resolveValue] | <code>\*</code> |
| [rejectValue] | <code>\*</code> |
<a name="Pending+reset"></a>
### pending.reset()
### pending.reset([error])
Resets to initial state.
**Kind**: instance method of [<code>Pending</code>](#Pending)
| Param | Type | Description |
| --- | --- | --- |
| [error] | <code>Error</code> | custom rejection error if promise is in pending state. |
<a name="Pendings"></a>

@@ -236,2 +255,3 @@

* [.rejectAll([reason])](#Pendings+rejectAll)
* [.waitAll()](#Pendings+waitAll) ⇒ <code>Promise</code>
* [.generateId()](#Pendings+generateId) ⇒ <code>String</code>

@@ -250,2 +270,3 @@

| [options.timeout] | <code>Number</code> | <code>0</code> | default timeout for all promises |
| [options.persistent] | <code>Number</code> | <code>false</code> | should list keep promises after fulfillment |

@@ -379,2 +400,9 @@ <a name="Pendings+add"></a>

<a name="Pendings+waitAll"></a>
### pendings.waitAll() ⇒ <code>Promise</code>
Waits for all promises to fulfill and returns object with resolved/rejected values.
**Kind**: instance method of [<code>Pendings</code>](#Pendings)
**Returns**: <code>Promise</code> - promise resolved with `{resolved: <Array>, rejected: <Array>}`
<a name="Pendings+generateId"></a>

@@ -381,0 +409,0 @@

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

this._isRejected = false;
this._value = undefined;
this._promise = null;

@@ -37,2 +38,11 @@ this._timer = null;

/**
* Returns value with that promise was fulfilled (resolved or rejected).
*
* @returns {*}
*/
get value() {
return this._value;
}
/**
* Returns true if promise resolved.

@@ -65,2 +75,11 @@ *

/**
* Returns true if promise is pending.
*
* @returns {Boolean}
*/
get isPending() {
return this._isPending;
}
/**
* Callback called when promise is fulfilled (resolved or rejected).

@@ -108,2 +127,3 @@ *

this._isResolved = true;
this._value = value;
this._clearTimer();

@@ -116,12 +136,13 @@ this._resolve(value);

/**
* Rejects pending promise with specified `reason`.
* Rejects pending promise with specified `value`.
*
* @param {*} [reason]
* @param {*} [value]
*/
reject(reason) {
reject(value) {
if (this._isPending) {
this._isPending = false;
this._isRejected = true;
this._value = value;
this._clearTimer();
this._reject(reason);
this._reject(value);
this._onFulfilled(this);

@@ -132,12 +153,12 @@ }

/**
* Helper method: rejects if `reason` is truthy, otherwise resolves with `value`.
* Helper method: rejects if `rejectValue` is truthy, otherwise resolves with `resolveValue`.
*
* @param {*} [value]
* @param {*} [reason]
* @param {*} [resolveValue]
* @param {*} [rejectValue]
*/
fulfill(value, reason) {
if (reason) {
this.reject(reason);
fulfill(resolveValue, rejectValue) {
if (rejectValue) {
this.reject(rejectValue);
} else {
this.resolve(value);
this.resolve(resolveValue);
}

@@ -160,2 +181,3 @@ }

this._isRejected = false;
this._value = undefined;
this._clearTimer();

@@ -184,3 +206,4 @@ }

try {
fn();
const res = fn();
this._proxyPromise(res);
} catch (e) {

@@ -201,4 +224,10 @@ this.reject(e);

}
_proxyPromise(p) {
if (p && typeof p.then === 'function') {
p.then(value => this.resolve(value), e => this.reject(e));
}
}
}
module.exports = Pending;

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

const DEFAULT_OPTIONS = {
idPrefix: '',
persistent: false,
timeout: 0,
};
class Pendings {

@@ -17,8 +23,8 @@ /**

* @param {Number} [options.timeout=0] default timeout for all promises
* @param {Number} [options.persistent=false] should list keep promises after fulfillment
*/
constructor(options) {
options = options || {};
this._timeout = options.timeout || 0;
this._idPrefix = options.idPrefix || '';
this._options = Object.assign({}, DEFAULT_OPTIONS, options);
this._map = Object.create(null);
this._waitingAll = new Pending();
}

@@ -55,3 +61,3 @@

const timeout = this._getTimeout(options);
pending.onFulfilled = () => delete this._map[id];
pending.onFulfilled = () => this._onFulfilled(id);
return pending.call(() => fn(id), timeout);

@@ -164,2 +170,11 @@ }

/**
* Waits for all promises to fulfill and returns object with resolved/rejected values.
*
* @returns {Promise} promise resolved with `{resolved: <Array>, rejected: <Array>}`
*/
waitAll() {
return this._waitingAll.call(() => this._checkAllFulfilled());
}
/**
* Generates unique ID. Can be overwritten.

@@ -170,9 +185,40 @@ *

generateId() {
return `${this._idPrefix}${Date.now()}-${Math.random()}`;
return `${this._options.idPrefix}${Date.now()}-${Math.random()}`;
}
_onFulfilled(id) {
if (!this._options.persistent) {
delete this._map[id];
}
if (this._waitingAll.isPending) {
this._checkAllFulfilled();
}
}
_getTimeout(options) {
options = options || {};
return options.timeout !== undefined ? options.timeout : this._timeout;
return options && options.timeout !== undefined ? options.timeout : this._options.timeout;
}
_checkAllFulfilled() {
const allFulfilled = Object.keys(this._map).every(id => this._map[id].isFulfilled);
if (allFulfilled) {
const result = this._getAllValues();
this._waitingAll.resolve(result);
this._waitingAll.reset();
}
}
_getAllValues() {
const resolved = {};
const rejected = {};
Object.keys(this._map).forEach(id => {
const pending = this._map[id];
if (pending.isResolved) {
resolved[id] = pending.value;
} else {
rejected[id] = pending.value;
}
});
return {resolved, rejected};
}
}

@@ -179,0 +225,0 @@

@@ -64,2 +64,12 @@ 'use strict';

});
it('should proxy resolve if fn returns promise', function () {
const res = this.pending.call(() => Promise.resolve('foo'));
return assert.eventually.equal(res, 'foo');
});
it('should proxy reject if fn returns promise', function () {
const res = this.pending.call(() => Promise.reject(new Error('err')));
return assert.isRejected(res, 'err');
});
});

@@ -74,2 +84,7 @@

it('should resolve inside fn', function () {
const res = this.pending.call(() => this.pending.resolve('foo'));
return assert.eventually.equal(res, 'foo');
});
it('should keep first value if resolved twice', function () {

@@ -101,2 +116,7 @@ const res = this.pending.call(noop);

it('should reject inside fn', function () {
const res = this.pending.call(() => this.pending.reject(new Error('err')));
return assert.isRejected(res, 'err');
});
it('should keep first value if rejected twice', function () {

@@ -135,2 +155,25 @@ const res = this.pending.call(noop);

describe('isPending', function () {
it('should be false until call', function () {
assert.notOk(this.pending.isPending);
});
it('should be true after call', function () {
this.pending.call();
assert.ok(this.pending.isPending);
});
it('should be false after resolve', function () {
this.pending.call();
this.pending.resolve('foo');
assert.notOk(this.pending.isPending);
});
it('should be false after reject', function () {
this.pending.call().catch(() => {});
this.pending.reject('foo');
assert.notOk(this.pending.isPending);
});
});
describe('isFulfilled', function () {

@@ -210,2 +253,16 @@ it('should set after resolve', function () {

describe('value', function () {
it('should return resolved value', function () {
this.pending.call();
this.pending.resolve('foo');
assert.equal(this.pending.value, 'foo');
});
it('should return rejected value', function () {
this.pending.call().catch(() => {});
this.pending.reject('err');
assert.equal(this.pending.value, 'err');
});
});
describe('timeout', function () {

@@ -212,0 +269,0 @@ it('should resolve before timeout', function () {

@@ -189,3 +189,84 @@ 'use strict';

describe('timeout', function () {
describe('rejectAll', function () {
it('should reject all promises', function () {
const p1 = this.pendings.add(noop);
const p2 = this.pendings.set(1, noop);
this.pendings.rejectAll('err');
return Promise.all([
assert.isRejected(p1, 'err'),
assert.isRejected(p2, 'err'),
]);
});
});
describe('waitAll', function () {
it('should resolve with empty for empty list', function () {
const pendings = new Pendings();
const res = pendings.waitAll();
return assert.eventually.deepEqual(res, {resolved: {}, rejected: {}});
});
it('should resolve with empty result for persistent: false', function () {
const pendings = new Pendings({persistent: false});
pendings.set(1, noop);
pendings.set(2, noop);
pendings.set(3, noop).catch(() => {});
const res = pendings.waitAll();
pendings.resolve(1, 'foo');
setTimeout(() => pendings.resolve(2, 'foo2'), 10);
pendings.reject(3);
return assert.eventually.deepEqual(res, {resolved: {}, rejected: {}});
});
it('should resolve with resolved/rejected values for persistent: true', function () {
const pendings = new Pendings({persistent: true});
pendings.set(1, noop);
pendings.set(2, noop);
pendings.set(3, () => Promise.resolve('bar'));
pendings.set(4, noop).catch(() => {});
const res = pendings.waitAll();
pendings.resolve(1, 'foo');
pendings.reject(4, 'err');
setTimeout(() => pendings.resolve(2, 'foo2'), 10);
return assert.eventually.deepEqual(res, {
resolved: {
'1': 'foo',
'2': 'foo2',
'3': 'bar'
},
rejected: {
'4': 'err'
}
});
});
it('should accumulate resolved values for several calls', function () {
const pendings = new Pendings({persistent: true});
pendings.set(1, noop);
pendings.resolve(1, 'foo');
const p1 = pendings.waitAll();
pendings.set(2, noop);
pendings.resolve(2, 'bar');
const p2 = pendings.waitAll();
return Promise.all([
assert.eventually.deepEqual(p1, {
resolved: {'1': 'foo'},
rejected: {},
}),
assert.eventually.deepEqual(p2, {
resolved: {'1': 'foo', '2': 'bar'},
rejected: {},
}),
]);
});
});
describe('generateId', function () {
it('should change generated ids', function () {
this.pendings.generateId = () => 1;
this.pendings.add(id => assert.equal(id, 1));
});
});
describe('options: timeout', function () {
it('should resolve before timeout', function () {

@@ -215,42 +296,43 @@ const res = this.pendings.set(1, noop, {timeout: 10});

describe('rejectAll', function () {
it('should reject all promises', function () {
const p1 = this.pendings.add(noop);
const p2 = this.pendings.set(1, noop);
this.pendings.rejectAll('err');
return Promise.all([
assert.isRejected(p1, 'err'),
assert.isRejected(p2, 'err'),
]);
describe('options: idPrefix', function () {
it('should set idPrefix', function () {
let id;
const pendings = new Pendings({idPrefix: 'client1'});
pendings.add(_id => id = _id);
assert.equal(id.indexOf('client1'), 0);
});
});
it('should overwrite generateId method', function () {
this.pendings.generateId = () => 1;
this.pendings.add(id => assert.equal(id, 1));
});
describe('options: persistent', function () {
it('should not store fulfilled pendings for persistent = false', function () {
const pendings = new Pendings({persistent: false});
pendings.set(1, noop);
pendings.set(2, noop).catch(() => {});
pendings.set(3, noop);
pendings.resolve(1);
pendings.reject(2);
assert.equal(Object.keys(pendings._map).length, 1);
});
it('should set idPrefix', function () {
let id;
const pendings = new Pendings({idPrefix: 'client1'});
pendings.add(_id => id = _id);
assert.equal(id.indexOf('client1'), 0);
it('should store fulfilled pendings for persistent = true', function () {
const pendings = new Pendings({persistent: true});
pendings.set(1, noop);
pendings.set(2, noop).catch(() => {});
pendings.set(3, noop);
pendings.resolve(1);
pendings.reject(2);
assert.equal(Object.keys(pendings._map).length, 3);
});
});
it('should export Pending', function () {
assert.ok(Pendings.Pending);
});
describe('exports', function () {
it('should export Pending', function () {
assert.ok(Pendings.Pending);
});
it('should export TimeoutError', function () {
assert.ok(Pendings.TimeoutError);
it('should export TimeoutError', function () {
assert.ok(Pendings.TimeoutError);
});
});
it('should not store fulfilled pendings', function () {
this.pendings.set(1, noop);
this.pendings.set(2, noop).catch(() => {});
this.pendings.set(3, noop);
this.pendings.resolve(1);
this.pendings.reject(2);
assert.equal(Object.keys(this.pendings._map).length, 1);
});
});
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