awaitable-array
Version:
Create an array that can be awaited for a specific length
94 lines (79 loc) • 2.57 kB
JavaScript
const Promise = require('bluebird');
/**
* Returns a Proxy for an Array (or specified array) which can be awaited until a certain length is reached.
* Use the following method: untilLength(length = 1, padding = 0, timeout = 2000)
* @constructor [...args] Array Arguments
* @returns {Proxy<Array>}
*/
class AwaitableArray extends Array {
constructor(...args) {
super(...args);
this.handlers = {};
return new Proxy(this, this.handlers);
}
/**
* Returns a Promise that Resolves when the array reaches a given length
* @param {number} length
* @param {number} [padding] - optional wait time in ms after the length is reached to resolve
* @param {number} [timeout] - optional timeout - defaults to 2000 ms
*/
untilLength(length = 1, padding = 0, timeout = 2000) {
return new Promise((resolve) => {
if (this.length >= length) {
delete this.handlers.set;
if (padding > 0) {
return Promise.delay(padding).then(resolve);
}
return resolve();
}
// Desired length not reached yet
this.handlers.set = (target, property, value) => {
target[property] = value;
if (target.length === length) {
if (padding > 0) {
Promise.delay(padding).then(resolve);
} else {
resolve();
}
}
return true;
};
}).timeout(timeout).catch(Promise.TimeoutError, (err) => {
delete this.handlers.set;
throw err;
});
}
/**
* Returns a Promise that Resolves when a condition is given
* @param {function} condition
* @param {number} [padding] - optional wait time in ms after the length is reached to resolve
* @param {number} [timeout] - optional timeout - defaults to 2000 ms
*/
untilCondition(condition, padding = 0, timeout = 2000) {
return new Promise((resolve) => {
if (condition(this)) {
delete this.handlers.set;
if (padding > 0) {
return Promise.delay(padding).then(resolve);
}
return resolve();
}
// Desired length not reached yet
this.handlers.set = (target, property, value) => {
target[property] = value;
if (condition(target)) {
if (padding > 0) {
Promise.delay(padding).then(resolve);
} else {
resolve();
}
}
return true;
};
}).timeout(timeout).catch(Promise.TimeoutError, (err) => {
delete this.handlers.set;
throw err;
});
}
}
module.exports = AwaitableArray;