Comparing version 0.1.8 to 0.1.9
@@ -11,2 +11,3 @@ /** | ||
var promiseFinally = require('promise.prototype.finally'); | ||
var Pending = require('./pending'); | ||
@@ -19,3 +20,3 @@ | ||
* @param {Object} [options] | ||
* @param {Number} [options.timeout] default timeout | ||
* @param {Number} [options.timeout] default timeout for all promises | ||
*/ | ||
@@ -35,3 +36,3 @@ function Pendings(options) { | ||
* @param {Object} [options] | ||
* @param {Number} [options.timeout] | ||
* @param {Number} [options.timeout] custom timeout for particular promise | ||
* @returns {Promise} | ||
@@ -54,3 +55,3 @@ */ | ||
* @param {Object} [options] | ||
* @param {Number} [options.timeout] | ||
* @param {Number} [options.timeout] custom timeout for particular promise | ||
* @returns {Promise} | ||
@@ -62,8 +63,15 @@ */ | ||
value: function set(id, fn, options) { | ||
options = options || {}; | ||
var timeout = options.timeout !== undefined ? options.timeout : this._timeout; | ||
var mainPromise = this._createPromise(id, fn); | ||
var finalPromise = timeout ? this._wrapWithTimeout(mainPromise, id, timeout) : mainPromise; | ||
this._setPromise(id, finalPromise); | ||
return finalPromise; | ||
var _this = this; | ||
if (!this.has(id)) { | ||
var pending = this._map[id] = new Pending(); | ||
var timeout = this._getTimeout(options); | ||
var promise = pending.call(function () { | ||
return fn(id); | ||
}, timeout); | ||
pending.finalPromise = promiseFinally(promise, function () { | ||
return delete _this._map[id]; | ||
}); | ||
} | ||
return this.getPromise(id); | ||
} | ||
@@ -94,3 +102,3 @@ | ||
value: function resolve(id, value) { | ||
var pending = this._extract(id); | ||
var pending = this._map[id]; | ||
if (pending) { | ||
@@ -111,3 +119,3 @@ pending.resolve(value); | ||
value: function reject(id, reason) { | ||
var pending = this._extract(id); | ||
var pending = this._map[id]; | ||
if (pending) { | ||
@@ -127,6 +135,6 @@ pending.reject(reason); | ||
value: function rejectAll(reason) { | ||
var _this = this; | ||
var _this2 = this; | ||
Object.keys(this._map).forEach(function (id) { | ||
return _this.reject(id, reason); | ||
return _this2.reject(id, reason); | ||
}); | ||
@@ -146,3 +154,3 @@ } | ||
value: function fulfill(id, value, reason) { | ||
var pending = this._extract(id); | ||
var pending = this._map[id]; | ||
if (pending) { | ||
@@ -178,53 +186,7 @@ pending.fulfill(value, reason); | ||
}, { | ||
key: '_extract', | ||
value: function _extract(id) { | ||
var pending = this._map[id]; | ||
if (pending) { | ||
delete this._map[id]; | ||
return pending; | ||
} | ||
key: '_getTimeout', | ||
value: function _getTimeout(options) { | ||
options = options || {}; | ||
return options.timeout !== undefined ? options.timeout : this._timeout; | ||
} | ||
}, { | ||
key: '_createPromise', | ||
value: function _createPromise(id, fn) { | ||
var _this2 = this; | ||
var pending = new Pending(); | ||
return pending.call(function () { | ||
if (_this2._map[id]) { | ||
throw new Error('Promise with id ' + id + ' is already pending'); | ||
} | ||
_this2._map[id] = pending; | ||
try { | ||
fn(id); | ||
} catch (e) { | ||
_this2.reject(id, e); | ||
} | ||
}); | ||
} | ||
}, { | ||
key: '_createTimeoutPromise', | ||
value: function _createTimeoutPromise(id, timeout) { | ||
var _this3 = this; | ||
return new Promise(function (resolve) { | ||
return setTimeout(resolve, timeout); | ||
}).then(function () { | ||
var error = new Error('Promise rejected by timeout (' + timeout + ' ms)'); | ||
_this3.reject(id, error); | ||
}); | ||
} | ||
}, { | ||
key: '_wrapWithTimeout', | ||
value: function _wrapWithTimeout(promise, id, timeout) { | ||
var timeoutPromise = this._createTimeoutPromise(id, timeout); | ||
return Promise.race([promise, timeoutPromise]); | ||
} | ||
}, { | ||
key: '_setPromise', | ||
value: function _setPromise(id, promise) { | ||
if (this._map[id]) { | ||
this._map[id].finalPromise = promise; | ||
} | ||
} | ||
}]); | ||
@@ -231,0 +193,0 @@ |
@@ -11,3 +11,5 @@ /** | ||
module.exports = function () { | ||
var promiseFinally = require('promise.prototype.finally'); | ||
var Pending = function () { | ||
/** | ||
@@ -40,15 +42,12 @@ * Constructor. | ||
* @param {Function} fn | ||
* @param {Number} [timeout=0] | ||
* @returns {Promise} | ||
*/ | ||
value: function call(fn) { | ||
var _this = this; | ||
value: function call(fn, timeout) { | ||
this._isFulfilled = false; | ||
this._promise = new Promise(function (resolve, reject) { | ||
_this._resolve = resolve; | ||
_this._reject = reject; | ||
if (fn) { | ||
fn(); | ||
} | ||
}); | ||
this._createPromise(fn); | ||
if (timeout) { | ||
this._wrapWithTimeout(timeout); | ||
} | ||
this._wrapWithFinally(); | ||
return this._promise; | ||
@@ -66,3 +65,2 @@ } | ||
value: function resolve(value) { | ||
this._isFulfilled = true; | ||
this._resolve(value); | ||
@@ -80,3 +78,2 @@ } | ||
value: function reject(reason) { | ||
this._isFulfilled = true; | ||
this._reject(reason); | ||
@@ -102,2 +99,34 @@ } | ||
}, { | ||
key: '_createPromise', | ||
value: function _createPromise(fn) { | ||
var _this = this; | ||
this._promise = new Promise(function (resolve, reject) { | ||
_this._resolve = resolve; | ||
_this._reject = reject; | ||
if (fn) { | ||
fn(); | ||
} | ||
}); | ||
} | ||
}, { | ||
key: '_wrapWithTimeout', | ||
value: function _wrapWithTimeout(timeout) { | ||
var timeoutPromise = new Promise(function (resolve, reject) { | ||
return setTimeout(function () { | ||
reject(new Error('Promise rejected by timeout (' + timeout + ' ms)')); | ||
}, timeout); | ||
}); | ||
this._promise = Promise.race([this._promise, timeoutPromise]); | ||
} | ||
}, { | ||
key: '_wrapWithFinally', | ||
value: function _wrapWithFinally() { | ||
var _this2 = this; | ||
this._promise = promiseFinally(this._promise, function () { | ||
return _this2._isFulfilled = true; | ||
}); | ||
} | ||
}, { | ||
key: 'promise', | ||
@@ -122,2 +151,4 @@ get: function get() { | ||
return Pending; | ||
}(); | ||
}(); | ||
module.exports = Pending; |
{ | ||
"name": "pendings", | ||
"version": "0.1.8", | ||
"version": "0.1.9", | ||
"description": "Better control of pending promises", | ||
@@ -22,2 +22,3 @@ "author": { | ||
"ci": "npm run code && npm test", | ||
"docs": "jsdoc2md --template README_TEMPLATE.md --files src/*.js > README.md", | ||
"release": "npm run code && npm test && npm version $VER && npm publish && git push --follow-tags --no-verify", | ||
@@ -46,2 +47,3 @@ "release-patch": "VER=patch npm run release", | ||
"husky": "^0.13.4", | ||
"jsdoc-to-markdown": "^3.0.0", | ||
"lint-staged": "^4.0.0", | ||
@@ -60,3 +62,6 @@ "mocha": "^3.4.2" | ||
], | ||
"license": "MIT" | ||
"license": "MIT", | ||
"dependencies": { | ||
"promise.prototype.finally": "^2.0.1" | ||
} | ||
} |
353
README.md
@@ -92,172 +92,221 @@ # Pendings | ||
### new Pendings(options) | ||
Controls list of pending promises. | ||
```js | ||
/** | ||
* Constructor. | ||
* | ||
* @param {Object} [options] | ||
* @param {Number} [options.timeout] default timeout | ||
*/ | ||
``` | ||
## Classes | ||
#### .add(fn, options) | ||
```js | ||
/** | ||
* Calls `fn` and returns new promise. `fn` gets generated unique `id` as parameter. | ||
* | ||
* @param {Function} fn | ||
* @param {Object} [options] | ||
* @param {Number} [options.timeout] | ||
* @returns {Promise} | ||
*/ | ||
``` | ||
<dl> | ||
<dt><a href="#Pendings">Pendings</a></dt> | ||
<dd></dd> | ||
<dt><a href="#Pending">Pending</a></dt> | ||
<dd></dd> | ||
</dl> | ||
#### .set(id, fn, options) | ||
```js | ||
/** | ||
* Calls `fn` and returns new promise with specified `id`. | ||
* | ||
* @param {String|Number} id | ||
* @param {Function} fn | ||
* @param {Object} [options] | ||
* @param {Number} [options.timeout] | ||
* @returns {Promise} | ||
*/ | ||
``` | ||
<a name="Pendings"></a> | ||
#### .has(id) | ||
```js | ||
/** | ||
* Checks if pending promise with specified `id` exists. | ||
* | ||
* @param {String|Number} id | ||
* @returns {Boolean} | ||
*/ | ||
``` | ||
#### .resolve(id, value) | ||
```js | ||
/** | ||
* Resolves pending promise by `id` with specified `value`. | ||
* | ||
* @param {String|Number} id | ||
* @param {*} [value] | ||
*/ | ||
``` | ||
## Pendings | ||
**Kind**: global class | ||
#### .reject(id, reason) | ||
```js | ||
/** | ||
* Rejects pending promise by `id` with specified `reason`. | ||
* | ||
* @param {String|Number} id | ||
* @param {*} [reason] | ||
*/ | ||
``` | ||
* [Pendings](#Pendings) | ||
* [new Pendings([options])](#new_Pendings_new) | ||
* [.add(fn, [options])](#Pendings+add) ⇒ <code>Promise</code> | ||
* [.set(id, fn, [options])](#Pendings+set) ⇒ <code>Promise</code> | ||
* [.has(id)](#Pendings+has) ⇒ <code>Boolean</code> | ||
* [.resolve(id, [value])](#Pendings+resolve) | ||
* [.reject(id, [reason])](#Pendings+reject) | ||
* [.rejectAll([reason])](#Pendings+rejectAll) | ||
* [.fulfill(id, [value], [reason])](#Pendings+fulfill) | ||
* [.getPromise(id)](#Pendings+getPromise) ⇒ <code>Promise</code> \| <code>undefined</code> | ||
* [.generateId()](#Pendings+generateId) ⇒ <code>String</code> | ||
#### .rejectAll(reason) | ||
```js | ||
/** | ||
* Rejects all pending promises with specified `reason`. Useful for cleanup. | ||
* | ||
* @param {*} [reason] | ||
*/ | ||
``` | ||
<a name="new_Pendings_new"></a> | ||
#### .fulfill(id, value, reason) | ||
```js | ||
/** | ||
* Rejects if `reason` is truthy, otherwise resolves with `value`. | ||
* | ||
* @param {String|Number} id | ||
* @param {*} [value] | ||
* @param {*} [reason] | ||
*/ | ||
``` | ||
### new Pendings([options]) | ||
Constructor. | ||
#### .getPromise(id) | ||
```js | ||
/** | ||
* Returns promise of pending object with specified `id`. | ||
* | ||
* @param {String|Number} id | ||
* @returns {Promise|undefined} | ||
*/ | ||
``` | ||
#### .generateId() | ||
```js | ||
/** | ||
* Generates unique ID. Can be overwritten. | ||
* | ||
* @returns {String} | ||
*/ | ||
``` | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| [options] | <code>Object</code> | | | ||
| [options.timeout] | <code>Number</code> | default timeout for all promises | | ||
<a name="Pendings+add"></a> | ||
### pendings.add(fn, [options]) ⇒ <code>Promise</code> | ||
Calls `fn` and returns new promise. `fn` gets generated unique `id` as parameter. | ||
**Kind**: instance method of [<code>Pendings</code>](#Pendings) | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| fn | <code>function</code> | | | ||
| [options] | <code>Object</code> | | | ||
| [options.timeout] | <code>Number</code> | custom timeout for particular promise | | ||
<a name="Pendings+set"></a> | ||
### pendings.set(id, fn, [options]) ⇒ <code>Promise</code> | ||
Calls `fn` and returns new promise with specified `id`. | ||
**Kind**: instance method of [<code>Pendings</code>](#Pendings) | ||
| Param | Type | Description | | ||
| --- | --- | --- | | ||
| id | <code>String</code> \| <code>Number</code> | | | ||
| fn | <code>function</code> | | | ||
| [options] | <code>Object</code> | | | ||
| [options.timeout] | <code>Number</code> | custom timeout for particular promise | | ||
<a name="Pendings+has"></a> | ||
### pendings.has(id) ⇒ <code>Boolean</code> | ||
Checks if pending promise with specified `id` exists. | ||
**Kind**: instance method of [<code>Pendings</code>](#Pendings) | ||
| Param | Type | | ||
| --- | --- | | ||
| id | <code>String</code> \| <code>Number</code> | | ||
<a name="Pendings+resolve"></a> | ||
### pendings.resolve(id, [value]) | ||
Resolves pending promise by `id` with specified `value`. | ||
**Kind**: instance method of [<code>Pendings</code>](#Pendings) | ||
| Param | Type | | ||
| --- | --- | | ||
| id | <code>String</code> \| <code>Number</code> | | ||
| [value] | <code>\*</code> | | ||
<a name="Pendings+reject"></a> | ||
### pendings.reject(id, [reason]) | ||
Rejects pending promise by `id` with specified `reason`. | ||
**Kind**: instance method of [<code>Pendings</code>](#Pendings) | ||
| Param | Type | | ||
| --- | --- | | ||
| id | <code>String</code> \| <code>Number</code> | | ||
| [reason] | <code>\*</code> | | ||
<a name="Pendings+rejectAll"></a> | ||
### pendings.rejectAll([reason]) | ||
Rejects all pending promises with specified `reason`. Useful for cleanup. | ||
**Kind**: instance method of [<code>Pendings</code>](#Pendings) | ||
| Param | Type | | ||
| --- | --- | | ||
| [reason] | <code>\*</code> | | ||
<a name="Pendings+fulfill"></a> | ||
### pendings.fulfill(id, [value], [reason]) | ||
Rejects if `reason` is truthy, otherwise resolves with `value`. | ||
**Kind**: instance method of [<code>Pendings</code>](#Pendings) | ||
| Param | Type | | ||
| --- | --- | | ||
| id | <code>String</code> \| <code>Number</code> | | ||
| [value] | <code>\*</code> | | ||
| [reason] | <code>\*</code> | | ||
<a name="Pendings+getPromise"></a> | ||
### pendings.getPromise(id) ⇒ <code>Promise</code> \| <code>undefined</code> | ||
Returns promise of pending object with specified `id`. | ||
**Kind**: instance method of [<code>Pendings</code>](#Pendings) | ||
| Param | Type | | ||
| --- | --- | | ||
| id | <code>String</code> \| <code>Number</code> | | ||
<a name="Pendings+generateId"></a> | ||
### pendings.generateId() ⇒ <code>String</code> | ||
Generates unique ID. Can be overwritten. | ||
**Kind**: instance method of [<code>Pendings</code>](#Pendings) | ||
<a name="Pending"></a> | ||
## Pending | ||
**Kind**: global class | ||
* [Pending](#Pending) | ||
* [new Pending()](#new_Pending_new) | ||
* [.promise](#Pending+promise) ⇒ <code>Promise</code> | ||
* [.isFulfilled](#Pending+isFulfilled) ⇒ <code>Boolean</code> | ||
* [.call(fn, [timeout])](#Pending+call) ⇒ <code>Promise</code> | ||
* [.resolve([value])](#Pending+resolve) | ||
* [.reject([reason])](#Pending+reject) | ||
* [.fulfill([value], [reason])](#Pending+fulfill) | ||
<a name="new_Pending_new"></a> | ||
### new Pending() | ||
Controls single pending promise. | ||
```js | ||
/** | ||
* Constructor. | ||
*/ | ||
``` | ||
Constructor. | ||
#### .call(fn) | ||
```js | ||
/** | ||
* Calls `fn`, returns new promise and holds `resolve` / `reject` callbacks. | ||
* | ||
* @param {Function} fn | ||
* @returns {Promise} | ||
*/ | ||
``` | ||
<a name="Pending+promise"></a> | ||
#### .resolve(value) | ||
```js | ||
/** | ||
* Resolves pending promise with specified `value`. | ||
* | ||
* @param {*} [value] | ||
*/ | ||
``` | ||
### pending.promise ⇒ <code>Promise</code> | ||
Returns promise itself. | ||
#### .reject(reason) | ||
```js | ||
/** | ||
* Rejects pending promise with specified `reason`. | ||
* | ||
* @param {*} [reason] | ||
*/ | ||
``` | ||
**Kind**: instance property of [<code>Pending</code>](#Pending) | ||
<a name="Pending+isFulfilled"></a> | ||
#### .fulfill(value, reason) | ||
```js | ||
/** | ||
* Rejects if `reason` is truthy, otherwise resolves with `value`. | ||
* | ||
* @param {*} [value] | ||
* @param {*} [reason] | ||
*/ | ||
``` | ||
### pending.isFulfilled ⇒ <code>Boolean</code> | ||
Returns is promise fulfilled or not. | ||
#### .isFulfilled | ||
```js | ||
/** | ||
* Returns is promise fulfilled or not. | ||
* | ||
* @returns {Boolean} | ||
*/ | ||
``` | ||
**Kind**: instance property of [<code>Pending</code>](#Pending) | ||
<a name="Pending+call"></a> | ||
#### .promise | ||
```js | ||
/** | ||
* Returns promise itself. | ||
* | ||
* @returns {Promise} | ||
*/ | ||
``` | ||
### pending.call(fn, [timeout]) ⇒ <code>Promise</code> | ||
Calls `fn`, returns new promise and holds `resolve` / `reject` callbacks. | ||
**Kind**: instance method of [<code>Pending</code>](#Pending) | ||
| Param | Type | Default | | ||
| --- | --- | --- | | ||
| fn | <code>function</code> | | | ||
| [timeout] | <code>Number</code> | <code>0</code> | | ||
<a name="Pending+resolve"></a> | ||
### pending.resolve([value]) | ||
Resolves pending promise with specified `value`. | ||
**Kind**: instance method of [<code>Pending</code>](#Pending) | ||
| Param | Type | | ||
| --- | --- | | ||
| [value] | <code>\*</code> | | ||
<a name="Pending+reject"></a> | ||
### pending.reject([reason]) | ||
Rejects pending promise with specified `reason`. | ||
**Kind**: instance method of [<code>Pending</code>](#Pending) | ||
| Param | Type | | ||
| --- | --- | | ||
| [reason] | <code>\*</code> | | ||
<a name="Pending+fulfill"></a> | ||
### pending.fulfill([value], [reason]) | ||
Rejects if `reason` is truthy, otherwise resolves with `value`. | ||
**Kind**: instance method of [<code>Pending</code>](#Pending) | ||
| Param | Type | | ||
| --- | --- | | ||
| [value] | <code>\*</code> | | ||
| [reason] | <code>\*</code> | | ||
## License | ||
MIT @ [Vitaliy Potapov](https://github.com/vitalets) |
@@ -7,2 +7,3 @@ /** | ||
const promiseFinally = require('promise.prototype.finally'); | ||
const Pending = require('./pending'); | ||
@@ -15,3 +16,3 @@ | ||
* @param {Object} [options] | ||
* @param {Number} [options.timeout] default timeout | ||
* @param {Number} [options.timeout] default timeout for all promises | ||
*/ | ||
@@ -29,3 +30,3 @@ constructor(options) { | ||
* @param {Object} [options] | ||
* @param {Number} [options.timeout] | ||
* @param {Number} [options.timeout] custom timeout for particular promise | ||
* @returns {Promise} | ||
@@ -44,12 +45,13 @@ */ | ||
* @param {Object} [options] | ||
* @param {Number} [options.timeout] | ||
* @param {Number} [options.timeout] custom timeout for particular promise | ||
* @returns {Promise} | ||
*/ | ||
set(id, fn, options) { | ||
options = options || {}; | ||
const timeout = options.timeout !== undefined ? options.timeout : this._timeout; | ||
const mainPromise = this._createPromise(id, fn); | ||
const finalPromise = timeout ? this._wrapWithTimeout(mainPromise, id, timeout) : mainPromise; | ||
this._setPromise(id, finalPromise); | ||
return finalPromise; | ||
if (!this.has(id)) { | ||
const pending = this._map[id] = new Pending(); | ||
const timeout = this._getTimeout(options); | ||
const promise = pending.call(() => fn(id), timeout); | ||
pending.finalPromise = promiseFinally(promise, () => delete this._map[id]); | ||
} | ||
return this.getPromise(id); | ||
} | ||
@@ -74,3 +76,3 @@ | ||
resolve(id, value) { | ||
const pending = this._extract(id); | ||
const pending = this._map[id]; | ||
if (pending) { | ||
@@ -88,3 +90,3 @@ pending.resolve(value); | ||
reject(id, reason) { | ||
const pending = this._extract(id); | ||
const pending = this._map[id]; | ||
if (pending) { | ||
@@ -112,3 +114,3 @@ pending.reject(reason); | ||
fulfill(id, value, reason) { | ||
const pending = this._extract(id); | ||
const pending = this._map[id]; | ||
if (pending) { | ||
@@ -138,43 +140,6 @@ pending.fulfill(value, reason); | ||
_extract(id) { | ||
const pending = this._map[id]; | ||
if (pending) { | ||
delete this._map[id]; | ||
return pending; | ||
} | ||
_getTimeout(options) { | ||
options = options || {}; | ||
return options.timeout !== undefined ? options.timeout : this._timeout; | ||
} | ||
_createPromise(id, fn) { | ||
const pending = new Pending(); | ||
return pending.call(() => { | ||
if (this._map[id]) { | ||
throw new Error(`Promise with id ${id} is already pending`); | ||
} | ||
this._map[id] = pending; | ||
try { | ||
fn(id); | ||
} catch (e) { | ||
this.reject(id, e); | ||
} | ||
}); | ||
} | ||
_createTimeoutPromise(id, timeout) { | ||
return new Promise(resolve => setTimeout(resolve, timeout)) | ||
.then(() => { | ||
const error = new Error(`Promise rejected by timeout (${timeout} ms)`); | ||
this.reject(id, error); | ||
}); | ||
} | ||
_wrapWithTimeout(promise, id, timeout) { | ||
const timeoutPromise = this._createTimeoutPromise(id, timeout); | ||
return Promise.race([promise, timeoutPromise]); | ||
} | ||
_setPromise(id, promise) { | ||
if (this._map[id]) { | ||
this._map[id].finalPromise = promise; | ||
} | ||
} | ||
} | ||
@@ -181,0 +146,0 @@ |
@@ -7,3 +7,5 @@ /** | ||
module.exports = class Pending { | ||
const promiseFinally = require('promise.prototype.finally'); | ||
class Pending { | ||
/** | ||
@@ -41,13 +43,12 @@ * Constructor. | ||
* @param {Function} fn | ||
* @param {Number} [timeout=0] | ||
* @returns {Promise} | ||
*/ | ||
call(fn) { | ||
call(fn, timeout) { | ||
this._isFulfilled = false; | ||
this._promise = new Promise((resolve, reject) => { | ||
this._resolve = resolve; | ||
this._reject = reject; | ||
if (fn) { | ||
fn(); | ||
} | ||
}); | ||
this._createPromise(fn); | ||
if (timeout) { | ||
this._wrapWithTimeout(timeout); | ||
} | ||
this._wrapWithFinally(); | ||
return this._promise; | ||
@@ -62,3 +63,2 @@ } | ||
resolve(value) { | ||
this._isFulfilled = true; | ||
this._resolve(value); | ||
@@ -73,3 +73,2 @@ } | ||
reject(reason) { | ||
this._isFulfilled = true; | ||
this._reject(reason); | ||
@@ -91,2 +90,25 @@ } | ||
} | ||
}; | ||
_createPromise(fn) { | ||
this._promise = new Promise((resolve, reject) => { | ||
this._resolve = resolve; | ||
this._reject = reject; | ||
if (fn) { | ||
fn(); | ||
} | ||
}); | ||
} | ||
_wrapWithTimeout(timeout) { | ||
const timeoutPromise = new Promise((resolve, reject) => setTimeout(() => { | ||
reject(new Error(`Promise rejected by timeout (${timeout} ms)`)); | ||
}, timeout)); | ||
this._promise = Promise.race([this._promise, timeoutPromise]); | ||
} | ||
_wrapWithFinally() { | ||
this._promise = promiseFinally(this._promise, () => this._isFulfilled = true); | ||
} | ||
} | ||
module.exports = Pending; |
@@ -84,2 +84,22 @@ 'use strict'; | ||
}); | ||
it('should set isFulfilled after reject (by error in fn)', function () { | ||
assert.ok(this.pending.isFulfilled); | ||
const res = this.pending.call(() => { throw new Error('err'); }); | ||
assert.notOk(this.pending.isFulfilled); | ||
return assert.isRejected(res, 'err') | ||
.then(() => assert.ok(this.pending.isFulfilled)); | ||
}); | ||
it('should resolve before timeout', function () { | ||
const res = this.pending.call(() => {}, 10); | ||
setTimeout(() => this.pending.resolve('foo'), 5); | ||
return assert.eventually.equal(res, 'foo'); | ||
}); | ||
it('should reject after timeout', function () { | ||
const res = this.pending.call(() => {}, 10); | ||
setTimeout(() => this.pending.resolve('foo'), 20); | ||
return assert.isRejected(res, 'Promise rejected by timeout (10 ms)'); | ||
}); | ||
}); |
@@ -57,5 +57,6 @@ 'use strict'; | ||
let id; | ||
this.pendings.add(pid => id = pid); | ||
const p = this.pendings.add(pid => id = pid); | ||
this.pendings.resolve(id, 'foo'); | ||
assert.notOk(this.pendings.has(id)); | ||
return assert.isFulfilled(p) | ||
.then(() => assert.notOk(this.pendings.has(id))); | ||
}); | ||
@@ -120,11 +121,12 @@ | ||
it('should delete promise after resolve', function () { | ||
this.pendings.set(1, () => {}); | ||
const p = this.pendings.set(1, () => {}); | ||
this.pendings.resolve(1, 1); | ||
assert.notOk(this.pendings.has(1)); | ||
return assert.isFulfilled(p) | ||
.then(() => assert.notOk(this.pendings.has(1))); | ||
}); | ||
it('should throw if called with the same id', function () { | ||
this.pendings.set(1, () => {}); | ||
const res = this.pendings.set(1, () => {}); | ||
return assert.isRejected(res, 'Promise with id 1 is already pending'); | ||
it('should return the same promise for second call with the same id', function () { | ||
const p1 = this.pendings.set(1, () => {}); | ||
const p2 = this.pendings.set(1, () => {}); | ||
assert.equal(p1, p2); | ||
}); | ||
@@ -170,12 +172,13 @@ | ||
it('should return false for resolved promise', function () { | ||
this.pendings.set(1, () => {}); | ||
const p = this.pendings.set(1, () => {}); | ||
this.pendings.resolve(1); | ||
assert.notOk(this.pendings.has(1)); | ||
return assert.isFulfilled(p) | ||
.then(() => assert.notOk(this.pendings.has(1))); | ||
}); | ||
it('should return false for rejected promise', function () { | ||
const res = this.pendings.set(1, () => {}); | ||
const p = this.pendings.set(1, () => {}); | ||
this.pendings.reject(1); | ||
assert.notOk(this.pendings.has(1)); | ||
return assert.isRejected(res); | ||
return assert.isRejected(p) | ||
.then(() => assert.notOk(this.pendings.has(1))); | ||
}); | ||
@@ -182,0 +185,0 @@ }); |
36966
11
312
1
9
787
+ Addedarray-buffer-byte-length@1.0.2(transitive)
+ Addedarraybuffer.prototype.slice@1.0.4(transitive)
+ Addedasync-function@1.0.0(transitive)
+ Addedavailable-typed-arrays@1.0.7(transitive)
+ Addedcall-bind@1.0.8(transitive)
+ Addedcall-bind-apply-helpers@1.0.2(transitive)
+ Addedcall-bound@1.0.3(transitive)
+ Addeddata-view-buffer@1.0.2(transitive)
+ Addeddata-view-byte-length@1.0.2(transitive)
+ Addeddata-view-byte-offset@1.0.1(transitive)
+ Addeddefine-data-property@1.1.4(transitive)
+ Addeddefine-properties@1.2.1(transitive)
+ Addeddunder-proto@1.0.1(transitive)
+ Addedes-abstract@1.23.9(transitive)
+ Addedes-define-property@1.0.1(transitive)
+ Addedes-errors@1.3.0(transitive)
+ Addedes-object-atoms@1.1.1(transitive)
+ Addedes-set-tostringtag@2.1.0(transitive)
+ Addedes-to-primitive@1.3.0(transitive)
+ Addedfor-each@0.3.5(transitive)
+ Addedfunction-bind@1.1.2(transitive)
+ Addedfunction.prototype.name@1.1.8(transitive)
+ Addedfunctions-have-names@1.2.3(transitive)
+ Addedget-intrinsic@1.2.7(transitive)
+ Addedget-proto@1.0.1(transitive)
+ Addedget-symbol-description@1.1.0(transitive)
+ Addedglobalthis@1.0.4(transitive)
+ Addedgopd@1.2.0(transitive)
+ Addedhas-bigints@1.1.0(transitive)
+ Addedhas-property-descriptors@1.0.2(transitive)
+ Addedhas-proto@1.2.0(transitive)
+ Addedhas-symbols@1.1.0(transitive)
+ Addedhas-tostringtag@1.0.2(transitive)
+ Addedhasown@2.0.2(transitive)
+ Addedinternal-slot@1.1.0(transitive)
+ Addedis-array-buffer@3.0.5(transitive)
+ Addedis-async-function@2.1.1(transitive)
+ Addedis-bigint@1.1.0(transitive)
+ Addedis-boolean-object@1.2.2(transitive)
+ Addedis-callable@1.2.7(transitive)
+ Addedis-data-view@1.0.2(transitive)
+ Addedis-date-object@1.1.0(transitive)
+ Addedis-finalizationregistry@1.1.1(transitive)
+ Addedis-generator-function@1.1.0(transitive)
+ Addedis-map@2.0.3(transitive)
+ Addedis-number-object@1.1.1(transitive)
+ Addedis-regex@1.2.1(transitive)
+ Addedis-set@2.0.3(transitive)
+ Addedis-shared-array-buffer@1.0.4(transitive)
+ Addedis-string@1.1.1(transitive)
+ Addedis-symbol@1.1.1(transitive)
+ Addedis-typed-array@1.1.15(transitive)
+ Addedis-weakmap@2.0.2(transitive)
+ Addedis-weakref@1.1.1(transitive)
+ Addedis-weakset@2.0.4(transitive)
+ Addedisarray@2.0.5(transitive)
+ Addedmath-intrinsics@1.1.0(transitive)
+ Addedobject-inspect@1.13.4(transitive)
+ Addedobject-keys@1.1.1(transitive)
+ Addedobject.assign@4.1.7(transitive)
+ Addedown-keys@1.0.1(transitive)
+ Addedpossible-typed-array-names@1.1.0(transitive)
+ Addedpromise.prototype.finally@2.0.1(transitive)
+ Addedreflect.getprototypeof@1.0.10(transitive)
+ Addedregexp.prototype.flags@1.5.4(transitive)
+ Addedsafe-array-concat@1.1.3(transitive)
+ Addedsafe-push-apply@1.0.0(transitive)
+ Addedsafe-regex-test@1.1.0(transitive)
+ Addedset-function-length@1.2.2(transitive)
+ Addedset-function-name@2.0.2(transitive)
+ Addedset-proto@1.0.0(transitive)
+ Addedside-channel@1.1.0(transitive)
+ Addedside-channel-list@1.0.0(transitive)
+ Addedside-channel-map@1.0.1(transitive)
+ Addedside-channel-weakmap@1.0.2(transitive)
+ Addedstring.prototype.trim@1.2.10(transitive)
+ Addedstring.prototype.trimend@1.0.9(transitive)
+ Addedstring.prototype.trimstart@1.0.8(transitive)
+ Addedtyped-array-buffer@1.0.3(transitive)
+ Addedtyped-array-byte-length@1.0.3(transitive)
+ Addedtyped-array-byte-offset@1.0.4(transitive)
+ Addedtyped-array-length@1.0.7(transitive)
+ Addedunbox-primitive@1.1.0(transitive)
+ Addedwhich-boxed-primitive@1.1.1(transitive)
+ Addedwhich-builtin-type@1.2.1(transitive)
+ Addedwhich-collection@1.0.2(transitive)
+ Addedwhich-typed-array@1.1.18(transitive)