{"id":26709393,"url":"https://github.com/js-bits/executor","last_synced_at":"2025-04-13T17:32:47.878Z","repository":{"id":57122331,"uuid":"356988592","full_name":"js-bits/executor","owner":"js-bits","description":"Abstract Executor class","archived":false,"fork":false,"pushed_at":"2023-07-19T02:07:08.000Z","size":990,"stargazers_count":3,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-25T02:43:38.608Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/js-bits.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-04-11T21:59:18.000Z","updated_at":"2023-07-03T17:58:03.000Z","dependencies_parsed_at":"2022-08-24T14:59:27.275Z","dependency_job_id":null,"html_url":"https://github.com/js-bits/executor","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/js-bits%2Fexecutor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/js-bits%2Fexecutor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/js-bits%2Fexecutor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/js-bits%2Fexecutor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/js-bits","download_url":"https://codeload.github.com/js-bits/executor/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248752375,"owners_count":21156080,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-03-27T08:16:44.760Z","updated_at":"2025-04-13T17:32:47.859Z","avatar_url":"https://github.com/js-bits.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Abstract Executor class\n\n`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.\n\n`Executor` also has two useful features:\n\n- Built-in monitoring of execution time\n- Optional rejection by a specified timeout\n\nThe package additionally includes a simple executor implementation called `Receiver`.\n\n## Installation\n\nInstall with npm:\n\n```\nnpm install @js-bits/executor\n```\n\nInstall with yarn:\n\n```\nyarn add @js-bits/executor\n```\n\nImport where you need it:\n\n```javascript\nimport { Executor, Receiver } from '@js-bits/executor';\n```\n\nor require for CommonJS:\n\n```javascript\nconst { Executor, Receiver } = require('@js-bits/executor');\n```\n\n## How to use\n\nSince asynchronous operation is decoupled it won't be executed automatically when a new `Executor` gets created. Instead you have to call `.execute()` method explicitly.\n\n```javascript\nconst asyncOperation = new Executor((resolve, reject) =\u003e {\n  // perform some asynchronous actions\n  // ...\n  // and resolve the promise when the operation is completed\n  resolve(123);\n});\n// ...\n// execute the operation where necessary\nasyncOperation.execute();\n// ...\n// handle the result\nasyncOperation.then(result =\u003e {\n  console.log('result', result); // 123\n});\n```\n\n## Execution timings\n\nThere are five metrics available any time through `timings` property:\n\n- `CREATED`\n- `EXECUTED`\n- `RESOLVED`\n- `REJECTED`\n- `SETTLED` (equals to either `RESOLVED` or `REJECTED`)\n\nUse `Executor.STATES` static enum property in order to access them.\n\n```javascript\n// create a new class of Executor\nclass DOMReadyReceiver extends Executor {\n  constructor(...args) {\n    super((resolve, reject) =\u003e {\n      if (document.readyState === 'complete' || document.readyState === 'interactive') {\n        resolve(true);\n      } else {\n        window.addEventListener('DOMContentLoaded', () =\u003e {\n          resolve(false);\n        });\n      }\n    }, ...args);\n    this.execute(); // let's execute it right away for the sake of demo\n  }\n}\n\n// create local state constants for convenience\nconst { CREATED, EXECUTED, RESOLVED } = DOMReadyReceiver.STATES;\n\n(async () =\u003e {\n  // create an instance of the class to be able to handle DOM Ready event\n  const domReady = new DOMReadyReceiver();\n  // wait for it to be resolved\n  const isDomReady = await domReady;\n\n  // check execution metrics\n  console.log(`DOMReadyReceiver created in ${domReady.timings[CREATED] / 1000} s`); // DOMReadyReceiver created in 0.629 s\n  console.log(`${isDomReady ? 'DOM ready' : 'DOMContentLoaded'} in ${domReady.timings[RESOLVED] / 1000} s`); // DOMContentLoaded in 0.644 s\n  console.log(`Delay: ${domReady.timings[RESOLVED] - domReady.timings[EXECUTED]} ms`); // Delay: 15 ms\n})();\n```\n\n## Timeout\n\nYou can use optional `timeout` parameter to set maximum allowable execution time for the asynchronous operation. There are 2 types of timeout supported:\n\n\u003cb\u003eHard timeout\u003c/b\u003e. 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.\n\n```javascript\nimport Timeout from '@js-bits/timeout';\n\nconst asyncOperation = new Executor(\n  (resolve, reject) =\u003e {\n    setTimeout(() =\u003e {\n      resolve(); // resolve the operation in about 1 second\n    }, 1000);\n  },\n  {\n    timeout: 100, // set timeout to 100 ms\n  }\n);\n\n(async () =\u003e {\n  const { EXECUTED, RESOLVED, SETTLED } = Executor.STATES;\n\n  asyncOperation.execute();\n  try {\n    await asyncOperation;\n    console.log(`Resolved in ${(asyncOperation.timings[RESOLVED] - asyncOperation.timings[EXECUTED]) / 1000} s`);\n  } catch (reason) {\n    // TimeoutExceededError: Operation timeout exceeded\n    if (reason.name === Timeout.TimeoutExceededError) {\n      console.log(`Timed out in ${asyncOperation.timings[SETTLED] - asyncOperation.timings[EXECUTED]} ms`); // Timed out in 104 ms\n    }\n  }\n})();\n```\n\n\u003cb\u003eSoft timeout\u003c/b\u003e. Can be set by a [Timeout](https://www.npmjs.com/package/@js-bits/timeout) instance passed as a value of `timeout` parameter. The executor won't be rejected automatically. The timeout must be handled externally.\n\n```javascript\nimport Timeout from '@js-bits/timeout';\n\nconst asyncOperation = new Executor(\n  (resolve, reject) =\u003e {\n    setTimeout(() =\u003e {\n      resolve('Success!!!'); // resolve the operation in about 1 second\n    }, 1000);\n  },\n  {\n    timeout: new Timeout(100),\n  }\n);\n\n(async () =\u003e {\n  asyncOperation.execute();\n  asyncOperation.timeout.catch(reason =\u003e {\n    if (reason.name === Timeout.TimeoutExceededError) {\n      // you can report that operation has timed out\n      console.log('Operation has exceeded specified timeout.'); // Operation has exceeded specified timeout.\n    }\n  });\n  // operation can still continue\n  console.log(await asyncOperation); // Success!!!\n})();\n```\n\n## Receiver\n\n`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.\n\n```javascript\nconst someAsyncValue = new Receiver();\nconst { EXECUTED, RESOLVED } = Receiver.STATES;\n\n(async () =\u003e {\n  setTimeout(() =\u003e {\n    someAsyncValue.resolve(123);\n  }, 1000);\n\n  console.log(`Received value: ${await someAsyncValue}`); // Received value: 123\n  console.log(`It took ${someAsyncValue.timings[RESOLVED] - someAsyncValue.timings[EXECUTED]} ms to receive the value`); // It took 1005 ms to receive the value\n})();\n```\n\n## Notes\n\n- [Loader](https://www.npmjs.com/package/@js-bits/loader) - an implementation of `Executor` for HTTP requests.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjs-bits%2Fexecutor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjs-bits%2Fexecutor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjs-bits%2Fexecutor/lists"}