@js-bits/executor v2.0.13
Abstract Executor class
Executor
is a class derived from Promise
and it has similar behavior but with one major difference: asynchronous operation that ties an outcome to a promise is decoupled from the constructor.
Executor
also has two useful features:
- Built-in monitoring of execution time
- Optional rejection by a specified timeout
The package additionally includes a simple executor implementation called Receiver
.
Installation
Install with npm:
npm install @js-bits/executor
Install with yarn:
yarn add @js-bits/executor
Import where you need it:
import { Executor, Receiver } from '@js-bits/executor';
or require for CommonJS:
const { Executor, Receiver } = require('@js-bits/executor');
How to use
Since asynchronous operation is decoupled it won't be executed automatically when a new Executor
gets created. Instead you have to call .execute()
method explicitly.
const asyncOperation = new Executor((resolve, reject) => {
// perform some asynchronous actions
// ...
// and resolve the promise when the operation is completed
resolve(123);
});
// ...
// execute the operation where necessary
asyncOperation.execute();
// ...
// handle the result
asyncOperation.then(result => {
console.log('result', result); // 123
});
Execution timings
There are five metrics available any time through timings
property:
CREATED
EXECUTED
RESOLVED
REJECTED
SETTLED
(equals to eitherRESOLVED
orREJECTED
)
Use Executor.STATES
static enum property in order to access them.
// create a new class of Executor
class DOMReadyReceiver extends Executor {
constructor(...args) {
super((resolve, reject) => {
if (document.readyState === 'complete' || document.readyState === 'interactive') {
resolve(true);
} else {
window.addEventListener('DOMContentLoaded', () => {
resolve(false);
});
}
}, ...args);
this.execute(); // let's execute it right away for the sake of demo
}
}
// create local state constants for convenience
const { CREATED, EXECUTED, RESOLVED } = DOMReadyReceiver.STATES;
(async () => {
// create an instance of the class to be able to handle DOM Ready event
const domReady = new DOMReadyReceiver();
// wait for it to be resolved
const isDomReady = await domReady;
// check execution metrics
console.log(`DOMReadyReceiver created in ${domReady.timings[CREATED] / 1000} s`); // DOMReadyReceiver created in 0.629 s
console.log(`${isDomReady ? 'DOM ready' : 'DOMContentLoaded'} in ${domReady.timings[RESOLVED] / 1000} s`); // DOMContentLoaded in 0.644 s
console.log(`Delay: ${domReady.timings[RESOLVED] - domReady.timings[EXECUTED]} ms`); // Delay: 15 ms
})();
Timeout
You can use optional timeout
parameter to set maximum allowable execution time for the asynchronous operation. There are 2 types of timeout supported:
Hard timeout. The executor will be automatically rejected when specified timeout is exceeded. It can be set by an integer number passed as a value of timeout
parameter.
import Timeout from '@js-bits/timeout';
const asyncOperation = new Executor(
(resolve, reject) => {
setTimeout(() => {
resolve(); // resolve the operation in about 1 second
}, 1000);
},
{
timeout: 100, // set timeout to 100 ms
}
);
(async () => {
const { EXECUTED, RESOLVED, SETTLED } = Executor.STATES;
asyncOperation.execute();
try {
await asyncOperation;
console.log(`Resolved in ${(asyncOperation.timings[RESOLVED] - asyncOperation.timings[EXECUTED]) / 1000} s`);
} catch (reason) {
// TimeoutExceededError: Operation timeout exceeded
if (reason.name === Timeout.TimeoutExceededError) {
console.log(`Timed out in ${asyncOperation.timings[SETTLED] - asyncOperation.timings[EXECUTED]} ms`); // Timed out in 104 ms
}
}
})();
Soft timeout. Can be set by a Timeout instance passed as a value of timeout
parameter. The executor won't be rejected automatically. The timeout must be handled externally.
import Timeout from '@js-bits/timeout';
const asyncOperation = new Executor(
(resolve, reject) => {
setTimeout(() => {
resolve('Success!!!'); // resolve the operation in about 1 second
}, 1000);
},
{
timeout: new Timeout(100),
}
);
(async () => {
asyncOperation.execute();
asyncOperation.timeout.catch(reason => {
if (reason.name === Timeout.TimeoutExceededError) {
// you can report that operation has timed out
console.log('Operation has exceeded specified timeout.'); // Operation has exceeded specified timeout.
}
});
// operation can still continue
console.log(await asyncOperation); // Success!!!
})();
Receiver
Receiver
does not accept any executor function which basically means that it doesn't perform any actions by itself. Receiver
can be used to asynchronously assign a value to some variable or indicate some event.
const someAsyncValue = new Receiver();
const { EXECUTED, RESOLVED } = Receiver.STATES;
(async () => {
setTimeout(() => {
someAsyncValue.resolve(123);
}, 1000);
console.log(`Received value: ${await someAsyncValue}`); // Received value: 123
console.log(`It took ${someAsyncValue.timings[RESOLVED] - someAsyncValue.timings[EXECUTED]} ms to receive the value`); // It took 1005 ms to receive the value
})();
Notes
- Loader - an implementation of
Executor
for HTTP requests.
12 months ago
12 months ago
11 months ago
12 months ago
12 months ago
12 months ago
11 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
12 months ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago