asva-executors
Advanced tools
Comparing version 0.0.12 to 0.0.13
@@ -1,5 +0,8 @@ | ||
import CacheExecutor from './modules/Executors/CacheExecutor'; | ||
import Executor from './modules/Executors/Executor'; | ||
import LadderExecutor from './modules/Executors/LadderExecutor'; | ||
import RepeatExecutor from './modules/Executors/RepeatExecutor'; | ||
export { CacheExecutor, Executor, LadderExecutor, RepeatExecutor }; | ||
import _CacheExecutor from './modules/Executors/CacheExecutor'; | ||
import _Executor from './modules/Executors/Executor'; | ||
import _LadderExecutor from './modules/Executors/LadderExecutor'; | ||
import _RepeatExecutor from './modules/Executors/RepeatExecutor'; | ||
export declare const CacheExecutor: typeof _CacheExecutor; | ||
export declare const Executor: typeof _Executor; | ||
export declare const LadderExecutor: typeof _LadderExecutor; | ||
export declare const RepeatExecutor: typeof _RepeatExecutor; |
@@ -82,3 +82,3 @@ /******/ (function(modules) { // webpackBootstrap | ||
"use strict"; | ||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _modules_Executors_CacheExecutor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./modules/Executors/CacheExecutor */ \"./src/modules/Executors/CacheExecutor.ts\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"CacheExecutor\", function() { return _modules_Executors_CacheExecutor__WEBPACK_IMPORTED_MODULE_0__[\"default\"]; });\n\n/* harmony import */ var _modules_Executors_Executor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./modules/Executors/Executor */ \"./src/modules/Executors/Executor.ts\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"Executor\", function() { return _modules_Executors_Executor__WEBPACK_IMPORTED_MODULE_1__[\"default\"]; });\n\n/* harmony import */ var _modules_Executors_LadderExecutor__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./modules/Executors/LadderExecutor */ \"./src/modules/Executors/LadderExecutor.ts\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"LadderExecutor\", function() { return _modules_Executors_LadderExecutor__WEBPACK_IMPORTED_MODULE_2__[\"default\"]; });\n\n/* harmony import */ var _modules_Executors_RepeatExecutor__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./modules/Executors/RepeatExecutor */ \"./src/modules/Executors/RepeatExecutor.ts\");\n/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, \"RepeatExecutor\", function() { return _modules_Executors_RepeatExecutor__WEBPACK_IMPORTED_MODULE_3__[\"default\"]; });\n\n\r\n\r\n\r\n\r\n\r\n\n\n//# sourceURL=webpack:///./src/index.ts?"); | ||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"CacheExecutor\", function() { return CacheExecutor; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Executor\", function() { return Executor; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"LadderExecutor\", function() { return LadderExecutor; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"RepeatExecutor\", function() { return RepeatExecutor; });\n/* harmony import */ var _modules_Executors_CacheExecutor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./modules/Executors/CacheExecutor */ \"./src/modules/Executors/CacheExecutor.ts\");\n/* harmony import */ var _modules_Executors_Executor__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./modules/Executors/Executor */ \"./src/modules/Executors/Executor.ts\");\n/* harmony import */ var _modules_Executors_LadderExecutor__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./modules/Executors/LadderExecutor */ \"./src/modules/Executors/LadderExecutor.ts\");\n/* harmony import */ var _modules_Executors_RepeatExecutor__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./modules/Executors/RepeatExecutor */ \"./src/modules/Executors/RepeatExecutor.ts\");\n\r\n\r\n\r\n\r\nvar CacheExecutor = _modules_Executors_CacheExecutor__WEBPACK_IMPORTED_MODULE_0__[\"default\"];\r\nvar Executor = _modules_Executors_Executor__WEBPACK_IMPORTED_MODULE_1__[\"default\"];\r\nvar LadderExecutor = _modules_Executors_LadderExecutor__WEBPACK_IMPORTED_MODULE_2__[\"default\"];\r\nvar RepeatExecutor = _modules_Executors_RepeatExecutor__WEBPACK_IMPORTED_MODULE_3__[\"default\"];\r\n\n\n//# sourceURL=webpack:///./src/index.ts?"); | ||
@@ -95,3 +95,3 @@ /***/ }), | ||
"use strict"; | ||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Executor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Executor */ \"./src/modules/Executors/Executor.ts\");\nvar __extends = (undefined && undefined.__extends) || (function () {\r\n var extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return function (d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n };\r\n})();\r\n\r\n/**\r\n * This executor caches first result\r\n */\r\nvar CacheExecutor = /** @class */ (function (_super) {\r\n __extends(CacheExecutor, _super);\r\n function CacheExecutor() {\r\n var _this = _super !== null && _super.apply(this, arguments) || this;\r\n _this.cachedPromise = null;\r\n return _this;\r\n }\r\n /**\r\n * @public\r\n */\r\n CacheExecutor.prototype.run = function () {\r\n var parameters = [];\r\n for (var _i = 0; _i < arguments.length; _i++) {\r\n parameters[_i] = arguments[_i];\r\n }\r\n if (!this.cachedPromise) {\r\n this.cachedPromise = _super.prototype.run.apply(this, parameters);\r\n }\r\n return this.cachedPromise;\r\n };\r\n CacheExecutor.prototype.runFresh = function () {\r\n var parameters = [];\r\n for (var _i = 0; _i < arguments.length; _i++) {\r\n parameters[_i] = arguments[_i];\r\n }\r\n this.cachedPromise = _super.prototype.run.apply(this, parameters);\r\n return this.cachedPromise;\r\n };\r\n CacheExecutor.prototype.cleanCache = function () {\r\n this.cachedPromise = null;\r\n };\r\n return CacheExecutor;\r\n}(_Executor__WEBPACK_IMPORTED_MODULE_0__[\"default\"]));\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (CacheExecutor);\r\n\n\n//# sourceURL=webpack:///./src/modules/Executors/CacheExecutor.ts?"); | ||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Executor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Executor */ \"./src/modules/Executors/Executor.ts\");\nvar __extends = (undefined && undefined.__extends) || (function () {\r\n var extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return function (d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n };\r\n})();\r\n\r\n/**\r\n * This executor caches first run result and provides it for all subsequent calls.\r\n */\r\nvar CacheExecutor = /** @class */ (function (_super) {\r\n __extends(CacheExecutor, _super);\r\n function CacheExecutor() {\r\n var _this = _super !== null && _super.apply(this, arguments) || this;\r\n _this.cachedPromise = null;\r\n return _this;\r\n }\r\n /**\r\n * Run command and cache promise.\r\n */\r\n CacheExecutor.prototype.run = function () {\r\n var parameters = [];\r\n for (var _i = 0; _i < arguments.length; _i++) {\r\n parameters[_i] = arguments[_i];\r\n }\r\n if (!this.cachedPromise) {\r\n this.cachedPromise = _super.prototype.run.apply(this, parameters);\r\n }\r\n return this.cachedPromise;\r\n };\r\n /**\r\n * Run executor without cache. Promise will be put to cache though.\r\n */\r\n CacheExecutor.prototype.runFresh = function () {\r\n var parameters = [];\r\n for (var _i = 0; _i < arguments.length; _i++) {\r\n parameters[_i] = arguments[_i];\r\n }\r\n this.cachedPromise = _super.prototype.run.apply(this, parameters);\r\n return this.cachedPromise;\r\n };\r\n /**\r\n * Just clean cache.\r\n */\r\n CacheExecutor.prototype.cleanCache = function () {\r\n this.cachedPromise = null;\r\n };\r\n return CacheExecutor;\r\n}(_Executor__WEBPACK_IMPORTED_MODULE_0__[\"default\"]));\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (CacheExecutor);\r\n\n\n//# sourceURL=webpack:///./src/modules/Executors/CacheExecutor.ts?"); | ||
@@ -108,3 +108,3 @@ /***/ }), | ||
"use strict"; | ||
eval("__webpack_require__.r(__webpack_exports__);\nvar Executor = /** @class */ (function () {\r\n function Executor(command) {\r\n this.wasLastRunFine = false; //\r\n this.runCount = 0; // Currently active commands count\r\n this.wasRun = false; // Executor was run at least once\r\n this.wasRunFine = false; // Executor was without throwing error at least once\r\n this.wasRunBad = false; //\r\n this.command = command;\r\n }\r\n Object.defineProperty(Executor.prototype, \"isRunning\", {\r\n get: function () {\r\n return !!this.runCount;\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n /**\r\n * @protected\r\n */\r\n Executor.prototype.beforeRun = function () {\r\n this.runCount++;\r\n };\r\n /**\r\n * @protected\r\n */\r\n Executor.prototype.afterRun = function (promise) {\r\n var _this = this;\r\n promise.then(function () {\r\n _this.runCount--;\r\n _this.setRunResultFlags(true);\r\n });\r\n promise.catch(function (result) {\r\n _this.runCount--;\r\n _this.setRunResultFlags(false);\r\n });\r\n };\r\n /**\r\n * @public\r\n */\r\n Executor.prototype.run = function () {\r\n var parameters = [];\r\n for (var _i = 0; _i < arguments.length; _i++) {\r\n parameters[_i] = arguments[_i];\r\n }\r\n this.beforeRun();\r\n var promise = this.command.apply(this, parameters);\r\n if (!(promise instanceof Promise)) {\r\n throw new Error('Executor command should return promise.');\r\n }\r\n this.afterRun(promise);\r\n return promise;\r\n };\r\n /**\r\n * @protected\r\n */\r\n Executor.prototype.setRunResultFlags = function (success) {\r\n this.wasRun = true;\r\n this.wasLastRunFine = success;\r\n if (success) {\r\n this.wasRunFine = true;\r\n }\r\n if (!success) {\r\n this.wasRunBad = true;\r\n }\r\n };\r\n return Executor;\r\n}());\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (Executor);\r\n\n\n//# sourceURL=webpack:///./src/modules/Executors/Executor.ts?"); | ||
eval("__webpack_require__.r(__webpack_exports__);\nvar Executor = /** @class */ (function () {\r\n function Executor(command) {\r\n /**\r\n * Currently running commands\r\n */\r\n this.runCount = 0; //\r\n /**\r\n * Last executor run happened without an error\r\n */\r\n this.wasLastRunFine = false; //\r\n /**\r\n * Executor was run at least once\r\n */\r\n this.wasRun = false;\r\n /**\r\n * Executor was run without throwing error at least once\r\n */\r\n this.wasRunFine = false;\r\n /**\r\n * Executor was run with thrown error at least once\r\n */\r\n this.wasRunBad = false;\r\n this.command = command;\r\n }\r\n Object.defineProperty(Executor.prototype, \"isRunning\", {\r\n /**\r\n * Command from this executor is currently running.\r\n */\r\n get: function () {\r\n return !!this.runCount;\r\n },\r\n enumerable: true,\r\n configurable: true\r\n });\r\n /**\r\n * @param parameters Arguments, will be passed down to command.\r\n * @returns {Promise<any>} Promise result is formed from whatever you returned from command.\r\n */\r\n Executor.prototype.run = function () {\r\n var parameters = [];\r\n for (var _i = 0; _i < arguments.length; _i++) {\r\n parameters[_i] = arguments[_i];\r\n }\r\n this.beforeRun();\r\n var promise = this.command.apply(this, parameters);\r\n if (!(promise instanceof Promise)) {\r\n throw new Error('Executor command should return promise.');\r\n }\r\n this.afterRun(promise);\r\n return promise;\r\n };\r\n Executor.prototype.beforeRun = function () {\r\n this.runCount++;\r\n };\r\n Executor.prototype.afterRun = function (promise) {\r\n var _this = this;\r\n promise.then(function () {\r\n _this.runCount--;\r\n _this.setRunResultFlags(true);\r\n });\r\n promise.catch(function () {\r\n _this.runCount--;\r\n _this.setRunResultFlags(false);\r\n });\r\n };\r\n Executor.prototype.setRunResultFlags = function (success) {\r\n this.wasRun = true;\r\n this.wasLastRunFine = success;\r\n if (success) {\r\n this.wasRunFine = true;\r\n }\r\n if (!success) {\r\n this.wasRunBad = true;\r\n }\r\n };\r\n return Executor;\r\n}());\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (Executor);\r\n\n\n//# sourceURL=webpack:///./src/modules/Executors/Executor.ts?"); | ||
@@ -121,3 +121,3 @@ /***/ }), | ||
"use strict"; | ||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Executor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Executor */ \"./src/modules/Executors/Executor.ts\");\nvar __extends = (undefined && undefined.__extends) || (function () {\r\n var extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return function (d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n };\r\n})();\r\n\r\n/**\r\n * This executor will chain requests ladder-like.\r\n * Last one will always be executed.\r\n */\r\nvar LadderExecutor = /** @class */ (function (_super) {\r\n __extends(LadderExecutor, _super);\r\n function LadderExecutor() {\r\n var _this = _super !== null && _super.apply(this, arguments) || this;\r\n /**\r\n * @private\r\n */\r\n _this.trigger = null;\r\n return _this;\r\n }\r\n /**\r\n * @public\r\n */\r\n LadderExecutor.prototype.run = function () {\r\n var _this = this;\r\n var parameters = [];\r\n for (var _i = 0; _i < arguments.length; _i++) {\r\n parameters[_i] = arguments[_i];\r\n }\r\n if (!this.isRunning) {\r\n var promise = _super.prototype.run.apply(this, parameters);\r\n promise.then(function () {\r\n _this.trigger && _this.trigger();\r\n _this.trigger = null;\r\n });\r\n return promise;\r\n }\r\n return new Promise(function (resolve) {\r\n _this.trigger = function () { return _this.run.apply(_this, parameters).then(resolve); };\r\n });\r\n };\r\n return LadderExecutor;\r\n}(_Executor__WEBPACK_IMPORTED_MODULE_0__[\"default\"]));\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (LadderExecutor);\r\n\n\n//# sourceURL=webpack:///./src/modules/Executors/LadderExecutor.ts?"); | ||
eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _Executor__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Executor */ \"./src/modules/Executors/Executor.ts\");\nvar __extends = (undefined && undefined.__extends) || (function () {\r\n var extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return function (d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n };\r\n})();\r\n\r\n/**\r\n * This executor will chain requests ladder-like.\r\n * Last one will always be executed.\r\n * For skipped requests the promise will never be resolved.\r\n */\r\nvar LadderExecutor = /** @class */ (function (_super) {\r\n __extends(LadderExecutor, _super);\r\n function LadderExecutor() {\r\n var _this = _super !== null && _super.apply(this, arguments) || this;\r\n _this.trigger = null;\r\n return _this;\r\n }\r\n LadderExecutor.prototype.run = function () {\r\n var _this = this;\r\n var parameters = [];\r\n for (var _i = 0; _i < arguments.length; _i++) {\r\n parameters[_i] = arguments[_i];\r\n }\r\n if (!this.isRunning) {\r\n var promise = _super.prototype.run.apply(this, parameters);\r\n promise.then(function () {\r\n _this.trigger && _this.trigger();\r\n _this.trigger = null;\r\n });\r\n return promise;\r\n }\r\n return new Promise(function (resolve) {\r\n _this.trigger = function () { return _this.run.apply(_this, parameters).then(resolve); };\r\n });\r\n };\r\n return LadderExecutor;\r\n}(_Executor__WEBPACK_IMPORTED_MODULE_0__[\"default\"]));\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (LadderExecutor);\r\n\n\n//# sourceURL=webpack:///./src/modules/Executors/LadderExecutor.ts?"); | ||
@@ -134,3 +134,3 @@ /***/ }), | ||
"use strict"; | ||
eval("__webpack_require__.r(__webpack_exports__);\nvar RepeatExecutor = /** @class */ (function () {\r\n function RepeatExecutor(command, time) {\r\n this.time = 100;\r\n this.id = null;\r\n this.command = command;\r\n this.time = time;\r\n }\r\n RepeatExecutor.prototype.start = function () {\r\n if (!this.id) {\r\n this.id = setInterval(this.command, this.time);\r\n }\r\n };\r\n RepeatExecutor.prototype.stop = function () {\r\n if (this.id) {\r\n clearInterval(this.id);\r\n }\r\n this.id = null;\r\n };\r\n return RepeatExecutor;\r\n}());\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (RepeatExecutor);\r\n\n\n//# sourceURL=webpack:///./src/modules/Executors/RepeatExecutor.ts?"); | ||
eval("__webpack_require__.r(__webpack_exports__);\n/**\r\n * Runs command on timeout.\r\n * Don't forget to stop it or executor would run indefinitely.\r\n */\r\nvar RepeatExecutor = /** @class */ (function () {\r\n function RepeatExecutor(command, time) {\r\n this.time = 100;\r\n this.id = null;\r\n this.command = command;\r\n this.time = time;\r\n }\r\n RepeatExecutor.prototype.start = function () {\r\n if (!this.id) {\r\n this.id = setInterval(this.command, this.time);\r\n }\r\n };\r\n RepeatExecutor.prototype.stop = function () {\r\n if (this.id) {\r\n clearInterval(this.id);\r\n }\r\n this.id = null;\r\n };\r\n return RepeatExecutor;\r\n}());\r\n/* harmony default export */ __webpack_exports__[\"default\"] = (RepeatExecutor);\r\n\n\n//# sourceURL=webpack:///./src/modules/Executors/RepeatExecutor.ts?"); | ||
@@ -137,0 +137,0 @@ /***/ }) |
import Executor from './Executor'; | ||
/** | ||
* This executor caches first result | ||
* This executor caches first run result and provides it for all subsequent calls. | ||
*/ | ||
export default class CacheExecutor extends Executor { | ||
cachedPromise: Promise<any> | null; | ||
protected cachedPromise: Promise<any> | null; | ||
/** | ||
* @public | ||
* Run command and cache promise. | ||
*/ | ||
run(...parameters: any[]): Promise<any>; | ||
/** | ||
* Run executor without cache. Promise will be put to cache though. | ||
*/ | ||
runFresh(...parameters: any[]): Promise<any>; | ||
/** | ||
* Just clean cache. | ||
*/ | ||
cleanCache(): void; | ||
} |
@@ -0,26 +1,37 @@ | ||
export declare type ExecutorCommand = (...args: any[]) => Promise<any>; | ||
export default class Executor { | ||
protected command: Function; | ||
protected command: ExecutorCommand; | ||
/** | ||
* Currently running commands | ||
*/ | ||
runCount: number; | ||
/** | ||
* Last executor run happened without an error | ||
*/ | ||
wasLastRunFine: boolean; | ||
runCount: number; | ||
/** | ||
* Executor was run at least once | ||
*/ | ||
wasRun: boolean; | ||
/** | ||
* Executor was run without throwing error at least once | ||
*/ | ||
wasRunFine: boolean; | ||
wasRunBad: boolean; | ||
constructor(command: (...args: any[]) => Promise<any>); | ||
readonly isRunning: boolean; | ||
/** | ||
* @protected | ||
* Executor was run with thrown error at least once | ||
*/ | ||
beforeRun(): void; | ||
wasRunBad: boolean; | ||
constructor(command: ExecutorCommand); | ||
/** | ||
* @protected | ||
* Command from this executor is currently running. | ||
*/ | ||
afterRun(promise: Promise<any>): void; | ||
readonly isRunning: boolean; | ||
/** | ||
* @public | ||
* @param parameters Arguments, will be passed down to command. | ||
* @returns {Promise<any>} Promise result is formed from whatever you returned from command. | ||
*/ | ||
run(...parameters: any[]): Promise<any>; | ||
/** | ||
* @protected | ||
*/ | ||
setRunResultFlags(success: boolean): void; | ||
protected beforeRun(): void; | ||
protected afterRun(promise: Promise<any>): void; | ||
protected setRunResultFlags(success: boolean): void; | ||
} |
@@ -5,12 +5,7 @@ import Executor from './Executor'; | ||
* Last one will always be executed. | ||
* For skipped requests the promise will never be resolved. | ||
*/ | ||
export default class LadderExecutor extends Executor { | ||
/** | ||
* @private | ||
*/ | ||
trigger: Function | null; | ||
/** | ||
* @public | ||
*/ | ||
private trigger; | ||
run(...parameters: any[]): Promise<any>; | ||
} |
@@ -0,1 +1,5 @@ | ||
/** | ||
* Runs command on timeout. | ||
* Don't forget to stop it or executor would run indefinitely. | ||
*/ | ||
export default class RepeatExecutor { | ||
@@ -5,5 +9,5 @@ command: Function; | ||
id: any; | ||
constructor(command: () => Promise<any>, time: number); | ||
constructor(command: Function, time: number); | ||
start(): void; | ||
stop(): void; | ||
} |
{ | ||
"name": "asva-executors", | ||
"version": "0.0.12", | ||
"version": "0.0.13", | ||
"description": "Helper classes for your async flow control", | ||
@@ -35,2 +35,4 @@ "main": "dist/src/index.js", | ||
"ts-loader": "^4.1.0", | ||
"typedoc": "^0.11.1", | ||
"typedoc-webpack-plugin": "^1.1.4", | ||
"typescript": "^2.6.1", | ||
@@ -37,0 +39,0 @@ "webpack": "~4.2.0", |
119
README.md
@@ -10,33 +10,120 @@ # asva-executors | ||
## Api | ||
## Intent | ||
To import class use: | ||
Conceptually, executors are just wrappers for asynchronous commands (functions). Yet they possess the following benefits: | ||
* They encapsulate the command, allowing it to be safely passed around without exposing its internals. | ||
* Provide utility methods for state monitoring. For instance, `executor.isRunning` tells whether executor runs command or not. Vanilla JS solutions often involve flags and are much clunkier. | ||
* Enforce specific logic for command execution. You can cache results, limit concurrent runs or even encapsulate into executor the logic for your lazy loaded list. | ||
Executors are low-level concept, so they might require a bit of time to wrap your head around. After that they're intuitive and fun to use. | ||
This library was not born on the spot and classes were used in various applications big and small by multiple developers for more than a year. Expect it to be reasonably refined and well thought. | ||
Library is armed with TypeScript declarations and tests. | ||
## Classes | ||
Available classes are: | ||
* **Executor** - basic executor (is extended by all other executors). | ||
* **CacheExecutor** - caches first result. | ||
* **LadderExecutor** - runs subsequent request only after previous one is finished. | ||
* **RepeatExecutor** - is just `setInterval` wrapped in class. | ||
Here are some possible use cases: | ||
* **Executor** - loaders (spinners), passing control through nested component structure. | ||
* **CacheExecutor** - one time requests (languages, configs, currencies), deep nested data aggregation. | ||
* **LadderExecutor** - live search. | ||
* **RepeatExecutor** - timed operations, websocket simulation and other hacks : 3. | ||
## Code and examples | ||
### Executor | ||
```javascript | ||
import { Executor } from 'asva-executors' | ||
// This command is just example. Yours should still return promise but hopefully be more useful : 3. | ||
const command = response => Promise.resolve(response) | ||
// Instantiate executor | ||
const executor = new Executor(command) | ||
// Run command and process results | ||
executor.run('data').then(result => console.log(result)) // Outputs 'data' to console | ||
// Do some checks | ||
executor.isRunning // Tells if executor currently runs command. | ||
executor.runCount // Show the number of currently running commands. There could be more than one, yes. | ||
executor.wasRun // Executor was run at least once | ||
executor.wasRunFine // Executor was run without throwing error at least once | ||
executor.wasRunBad // Executor was run with thrown error at least once | ||
executor.wasLastRunFine // Last executor run happened without an error | ||
``` | ||
The library provides you with the following classes: | ||
### CacheExecutor | ||
### Executor | ||
#### Props | ||
```javascript | ||
// We intend to make an expensive ajax call from several places. | ||
import { CacheExecutor } from 'asva-executors' | ||
const executor = new Executor(ajaxExpensiveCall) | ||
Chances are, the only prop you'll use is `isRunning` | ||
* isRunning - | ||
* wasLastRunFine - | ||
* runCount - | ||
* wasRun - | ||
* wasRunFine - | ||
* wasRunBad - | ||
// Run the same executor in a number of places simultaneously or not. | ||
// Command will be executed only once. | ||
const result = await executor.run() | ||
// If you have to load anew. | ||
executor.runFresh() | ||
``` | ||
### LadderExecutor | ||
```javascript | ||
import { Executor } from 'asva-executors' | ||
``` | ||
// This example is live search. | ||
import { LadderExecutor } from 'asva-executors' | ||
const executor = new Executor(liveSearchCall) | ||
// Imagine the case when user takes a nap on his keyboard. | ||
executor.run('a') // This request will be run | ||
executor.run('aa') // This request won't be run | ||
executor.run('aaa') // This request won't be run | ||
executor.run('aaaa') // This request will be run only after first one resolves. | ||
// So, in total you have 2 requests instead of 4. | ||
``` | ||
### RepeatExecutor | ||
```javascript | ||
// Being too lazy to implement websockets we decide to check notifications every ten seconds. | ||
import { RepeatExecutor } from 'asva-executors' | ||
const executor = new RepeatExecutor(checkNotificationsCall, 10000) | ||
// Start checking notifications | ||
executor.start() | ||
// Stop checking notifications | ||
executor.stop() | ||
``` | ||
You have to stop `RepeatExecutor` if you don't need it anymore. Similar to `setInterval` command it won't be garbage collected until then. | ||
----------------------- | ||
Feel free to check [source code][source-code-link] or tests to get better understanding. Library exposes typings so your IDE should comfortably provide type-hinting. | ||
## Fun facts | ||
* Name "executor" was taken from [Java][java-executor-url] and is quite similar conceptually. | ||
## Issues | ||
* Bugs will be addressed in timely manner. | ||
* More-less library is **done**. But feel free to share your idea of improvement. | ||
* More-less library is *done*. But feel free to share your idea of improvement. | ||
## Licence | ||
MIT | ||
MIT | ||
[java-executor-url]: https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Executor.html | ||
[source-code-link]: src/modules |
const config = require('./config.js') | ||
const CleanWebpackPlugin = require('clean-webpack-plugin') | ||
const TypedocWebpackPlugin = require('typedoc-webpack-plugin') | ||
@@ -37,4 +38,7 @@ module.exports = function () { | ||
new CleanWebpackPlugin(['dist'], { root: config.FOLDERS.ROOT }), | ||
new TypedocWebpackPlugin({ | ||
target: 'es2017', | ||
}), | ||
], | ||
} | ||
} |
@@ -1,11 +0,9 @@ | ||
import CacheExecutor from './modules/Executors/CacheExecutor' | ||
import Executor from './modules/Executors/Executor' | ||
import LadderExecutor from './modules/Executors/LadderExecutor' | ||
import RepeatExecutor from './modules/Executors/RepeatExecutor' | ||
import _CacheExecutor from './modules/Executors/CacheExecutor' | ||
import _Executor from './modules/Executors/Executor' | ||
import _LadderExecutor from './modules/Executors/LadderExecutor' | ||
import _RepeatExecutor from './modules/Executors/RepeatExecutor' | ||
export { | ||
CacheExecutor, | ||
Executor, | ||
LadderExecutor, | ||
RepeatExecutor, | ||
} | ||
export const CacheExecutor = _CacheExecutor | ||
export const Executor = _Executor | ||
export const LadderExecutor = _LadderExecutor | ||
export const RepeatExecutor = _RepeatExecutor |
import Executor from './Executor' | ||
/** | ||
* This executor caches first result | ||
* This executor caches first run result and provides it for all subsequent calls. | ||
*/ | ||
export default class CacheExecutor extends Executor { | ||
cachedPromise: Promise<any> | null = null | ||
protected cachedPromise: Promise<any> | null = null | ||
/** | ||
* @public | ||
* Run command and cache promise. | ||
*/ | ||
run (...parameters: any[]): Promise<any> { | ||
public run (...parameters: any[]): Promise<any> { | ||
if (!this.cachedPromise) { | ||
@@ -20,3 +19,6 @@ this.cachedPromise = super.run(...parameters) | ||
runFresh (...parameters: any[]): Promise<any> { | ||
/** | ||
* Run executor without cache. Promise will be put to cache though. | ||
*/ | ||
public runFresh (...parameters: any[]): Promise<any> { | ||
this.cachedPromise = super.run(...parameters) | ||
@@ -26,5 +28,8 @@ return this.cachedPromise | ||
cleanCache () { | ||
/** | ||
* Just clean cache. | ||
*/ | ||
public cleanCache () { | ||
this.cachedPromise = null | ||
} | ||
} |
@@ -0,43 +1,47 @@ | ||
export type ExecutorCommand = (...args: any[]) => Promise<any> | ||
export default class Executor { | ||
protected command: Function | ||
protected command: ExecutorCommand | ||
wasLastRunFine: boolean = false // | ||
runCount: number = 0 // Currently active commands count | ||
wasRun: boolean = false // Executor was run at least once | ||
wasRunFine: boolean = false // Executor was without throwing error at least once | ||
wasRunBad: boolean = false // | ||
/** | ||
* Currently running commands | ||
*/ | ||
public runCount: number = 0 // | ||
constructor (command: (...args: any[]) => Promise<any>) { | ||
this.command = command | ||
} | ||
/** | ||
* Last executor run happened without an error | ||
*/ | ||
public wasLastRunFine: boolean = false // | ||
get isRunning (): boolean { | ||
return !!this.runCount | ||
} | ||
/** | ||
* Executor was run at least once | ||
*/ | ||
public wasRun: boolean = false | ||
/** | ||
* @protected | ||
* Executor was run without throwing error at least once | ||
*/ | ||
beforeRun (): void { | ||
this.runCount++ | ||
public wasRunFine: boolean = false | ||
/** | ||
* Executor was run with thrown error at least once | ||
*/ | ||
public wasRunBad: boolean = false | ||
constructor (command: ExecutorCommand) { | ||
this.command = command | ||
} | ||
/** | ||
* @protected | ||
* Command from this executor is currently running. | ||
*/ | ||
afterRun (promise: Promise<any>): void { | ||
promise.then(() => { | ||
this.runCount-- | ||
this.setRunResultFlags(true) | ||
}) | ||
promise.catch((result) => { | ||
this.runCount-- | ||
this.setRunResultFlags(false) | ||
}) | ||
public get isRunning (): boolean { | ||
return !!this.runCount | ||
} | ||
/** | ||
* @public | ||
* @param parameters Arguments, will be passed down to command. | ||
* @returns {Promise<any>} Promise result is formed from whatever you returned from command. | ||
*/ | ||
run (...parameters: any[]): Promise<any> { | ||
public run (...parameters: any[]): Promise<any> { | ||
this.beforeRun() | ||
@@ -52,6 +56,18 @@ const promise = this.command(...parameters) | ||
/** | ||
* @protected | ||
*/ | ||
setRunResultFlags (success: boolean) { | ||
protected beforeRun (): void { | ||
this.runCount++ | ||
} | ||
protected afterRun (promise: Promise<any>): void { | ||
promise.then(() => { | ||
this.runCount-- | ||
this.setRunResultFlags(true) | ||
}) | ||
promise.catch(() => { | ||
this.runCount-- | ||
this.setRunResultFlags(false) | ||
}) | ||
} | ||
protected setRunResultFlags (success: boolean): void { | ||
this.wasRun = true | ||
@@ -58,0 +74,0 @@ this.wasLastRunFine = success |
@@ -6,13 +6,8 @@ import Executor from './Executor' | ||
* Last one will always be executed. | ||
* For skipped requests the promise will never be resolved. | ||
*/ | ||
export default class LadderExecutor extends Executor { | ||
/** | ||
* @private | ||
*/ | ||
trigger: Function | null = null | ||
private trigger: Function | null = null | ||
/** | ||
* @public | ||
*/ | ||
run (...parameters: any[]): Promise<any> { | ||
public run (...parameters: any[]): Promise<any> { | ||
if (!this.isRunning) { | ||
@@ -19,0 +14,0 @@ const promise = super.run(...parameters) |
@@ -0,1 +1,5 @@ | ||
/** | ||
* Runs command on timeout. | ||
* Don't forget to stop it or executor would run indefinitely. | ||
*/ | ||
export default class RepeatExecutor { | ||
@@ -6,3 +10,3 @@ command: Function | ||
constructor (command: () => Promise<any>, time: number) { | ||
constructor (command: Function, time: number) { | ||
this.command = command | ||
@@ -12,3 +16,3 @@ this.time = time | ||
public start () { | ||
public start (): void { | ||
if (!this.id) { | ||
@@ -19,3 +23,3 @@ this.id = setInterval(this.command, this.time) | ||
public stop () { | ||
public stop (): void { | ||
if (this.id) { | ||
@@ -22,0 +26,0 @@ clearInterval(this.id) |
43049
790
128
24