{"id":21186606,"url":"https://github.com/fetchte/abettor","last_synced_at":"2025-07-20T09:08:30.108Z","repository":{"id":57171995,"uuid":"98680052","full_name":"fetchTe/abettor","owner":"fetchTe","description":"An async/sync mediator pattern for event dispatching.","archived":false,"fork":false,"pushed_at":"2018-10-03T16:51:03.000Z","size":356,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-14T09:17:03.015Z","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":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fetchTe.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-07-28T19:10:12.000Z","updated_at":"2023-07-02T12:32:36.000Z","dependencies_parsed_at":"2022-08-24T13:30:46.130Z","dependency_job_id":null,"html_url":"https://github.com/fetchTe/abettor","commit_stats":null,"previous_names":["fetchte/abettor","artisin/abettor"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/fetchTe/abettor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fetchTe%2Fabettor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fetchTe%2Fabettor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fetchTe%2Fabettor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fetchTe%2Fabettor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fetchTe","download_url":"https://codeload.github.com/fetchTe/abettor/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fetchTe%2Fabettor/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259790795,"owners_count":22911572,"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":"2024-11-20T18:24:38.404Z","updated_at":"2025-06-19T01:35:49.054Z","avatar_url":"https://github.com/fetchTe.png","language":"JavaScript","readme":"# Abettor\n\n[![license](http://img.shields.io/badge/license-mit-3498db.svg)](https://github.com/artisin/abettor/blob/master/LICENSE)\n[![npm](https://img.shields.io/npm/v/abettor.svg)](https://github.com/artisin/abettor/blob/master/LICENSE)\n[![Dependencies Status](https://david-dm.org/artisin/abettor.svg)](https://david-dm.org/artisin/abettor)\n[![wercker status](https://app.wercker.com/status/7118d559df30262b7197acecb7b35ed4/s/master \"wercker status\")](https://app.wercker.com/project/byKey/7118d559df30262b7197acecb7b35ed4)\n\n## About\n\nAbettor helps you manage and emit events through a mediator pattern that allows you to dispatch events. Unlike other event emitting libraries Abettor can be used asynchronously or synchronously in a blocking or non-blocking manner to give you complete control any way you want it.\n\n## Install\n\nYou can either install Abettor via npm:\n\n```bash\n   yarn add abettor \n```\n\nAlternatively, you can download/copy one of files in the `/dist` folder depending on your use-case:\n\n+ `dist/abettor.js` - The node build for use with webpack and the like\n+ `dist/abettor-browser.js` - The browser build includes all the various library dependancies\n+ `dist/abettor-browser.min.js` - The minified version of browser version\n\n\n## Use Cases\n\nOne of the best use cases and the reason I built Abettor is to handel DOM events specifically the scroll event. For example, let's say you have multiple DOM events that listen to the window scroll event. Plus these events need to be trigged in a specific order and the various logic is speard out across multiple files.\n\nInherently things get messy quickly if you want a single source of truth and a non-blocking architecture. However, Abettor makes this a trivial matter so that you don't have to roll-out some janky promise chain. The follow example demenstrates how you can easly accomplish this use case in a clean and sane manner.\n\n\n\n```js\n// Event emitter in a events.js file - to make things simple\n// we'll make this Abettor instance avalible globally through window.\n// We all tell Abettor \nconst abettor = new Abettor();\nwindow._abettor = abettor;\n// Because we want these DOM events to happend one after another in a\n// synchronous nature but also be non-blocking\nwindow.addEventListener('scroll', (e) =\u003e abettor.emit('scroll', e, {async: false})));\n\n// component-1.js file -\u003e called 3rd\nwindow._abettor.on('scroll', (e) =\u003e console.log(`Comp-1 trigged at: ${e.timeStamp}`), {order: 2});\n\n// component-2.js file -\u003e called 1st\nwindow._abettor.on('scroll', (e) =\u003e {\n  // some logic that takes 500ms to complete\n  return new Promise((resolve) =\u003e setTimeout(() =\u003e {\n    console.log(`Comp-2 trigged at: ${e.timeStamp}`);\n    // need to resolve promise to let Abettor know it can move onto the next event\n    resolve();\n  }, 500));\n}, {order: 0});\n\n\n// component-3.js file -\u003e called 2nd\nwindow._abettor.on('scroll', (e) =\u003e console.log(`Comp-3 trigged at: ${e.timeStamp}`), {order: 1});\n```\n\n\n\n## Mode of Operation\n\nBy default Abettor uses an `async/await` wrapper to process/trigger events __unless__ the `blocking: true` option is specified. As demonstrated by the above example this allows for a synchronous mode of operation that is also non-blocking. That being said, the default mode of operation for Abettor is asynchronous in nature and is comparable to `Promise.all`. However, unlike `Promise.all` Abettor does not implement fail-fast behavior. That is, if an `on` event throws an error it will not stop the other `on` events from firing/processing. To really drive home this idea here is another synchronous example — the numbers represent when the `console.log` is fired. Also need be check out `/__tests__` for more examples.\n\n\n```js\nconst notAsync = new Abettor({async: false});\n\n// setTimeout helper\nconst timer = (cb, time = 500) =\u003e\n  new Promise((resolve) =\u003e {setTimeout(() =\u003e {resolve(cb());}, time);});\n\n// 1) called immediately\nnotAsync.on('test', () =\u003e console.log('start'));\n// 3) called after 1.5s\nnotAsync.on('test', () =\u003e timer(() =\u003e console.log('one'), 1500));\n// 4) after the above func resolves this func is invoked and called after 0.5s\n// thus 'two' is console logged after 2s\nnotAsync.on('test', () =\u003e timer(() =\u003e console.log('two')));\n// 5) this func is call immediatley after 'two'\nnotAsync.on('test', () =\u003e console.log('end'));\n\n// Triggers on events\nnotAsync.emit('test');\n// 2) Since Abettor is non-blocking this is fired right after 'start'\nconsole.log('Other Process');\n```\n\n\n\n\n\n## Constructor\n\nAbettor is a JavaScript class and the class constructor accepts an option object. The constructor options are inherited by all `emit` methods of the instance, although, you can override these set options through the option object on the `emit` method.\n\n+ `async: true`\n    * By default Abettor is asynchronous in opperation. To use it synchronously you must pass `false` to the `async` option.\n+ `blocking: false`\n    * By default Abettor uses an `async/await` wrapper in calling both synchronous or asynchronous events so that events are called in a non-blocking manner. However, you can call synchronous events in a blocking manner by passing `true` to the blocking option.\n+ `typeCheck: true`\n    * Employs basic argument checking to help avoid errors on all methods.\n\n\n```js\n// import/require\nimport Abettor from 'abettor';\n\n// create instance\nconst abettor = new Abettor({\n  // set default instance options\n});\n```\n\n\n## `emit` \u0026 `on`\n\nThe `emit` and `on` methods are the bread and butter of Abettor. Put simply, the `on` method subscribes to a corresponding `emit` method and when that `emit` method is invoked all subscribed `on` methods are triggered(invoked).\n\n__`emit(\u003cString:event\u003e[, ...args, \u003cObject:option{async, blocking, done}\u003e])`__\n\nThe only required argument for the `emit` method is a string that represents the event to which an `on` methods subscribes to. Arguments can also be passed to the `emit` method and in turn these arguments will be passed to each subscribed `on` method. Lastly, an `option` object can be passed as the last argument to override the default Abettor options as well as signal completion through the `done` method.\n\n__`on(\u003cString:event\u003e, \u003cFunction\u003e[, \u003cObject:option{once, order}\u003e])`__\n\nThe `on` method is composed of two required arguments. The first argument is a string that represents the `emit` event to which the `on` method subscribes to. The second argument is the function to be called if/once the `emit` event is fired. Additionally, you can pass an `option` object argument to specify the specific `order` to which the method is triggered and/or if the method is only to be triggered `once`.\n\n\n__Basic `emit` \u0026 `on` Example__\n\n```js\nabettor.on('myEvent', (my, arguments) =\u003e {\n  // event 1\n});\nabettor.on('myEvent', (my, arguments) =\u003e {\n  // event 2\n});\n\n// once invoked it triggers both on events\nabettor.emit('myEvent', 'my', 'arguments', {\n  async: true,\n  done: () =\u003e {\n    // invoked when event 1 \u0026 2 have completed\n  }\n})\n```\n\n\n## `remove` \u0026 `snapshot`\n\nThe `remove` and `snapshot` methods are more or less auxiliary method that can be helpful for certain use cases but in general aren’t used with much frequency.\n\n__`remove(\u003cString:event\u003e[, \u003cIndex | Function\u003e])`__\n\nAs the name implies the `remove` method un-subscribes all or a specific `on` method. If no second argument is passed to the `remove` method all subscribed `on` methods are removed. Alterntaivly, you can pass either the function on the `on` method that is to be removed or the specific index.\n\n\n```js\nabettor.on('myEvent', (my, arguments) =\u003e console.log('one'));\nabettor.on('myEvent', (my, arguments) =\u003e console.log('two'));\n\n// Both subscribed on's are triggered \nabettor.emit('myEvent');\n\n// Removes the second on method\nabettor.remove('myEvent', 1);\n\n// Only the first subscribed on method is triggered \nabettor.emit('myEvent');\n```\n\n\n\n__`snapshot(\u003cString:event\u003e, \u003cString:target-method\u003e[, ...args])`__\n\nThe `snapshot` method takes a snapshot of the current state and the target method in question and returns a function to be invoked at a later time. For example, once a remove `snapshot` is taken the only `on` subscribers that will be removed are the ones active at the time of the `snapshot`. The other use case for `snapshot` is to use it with the `emit` method.\n\n```js\nabettor.on('myEvent', (my, arguments) =\u003e console.log('one'));\nabettor.on('myEvent', (my, arguments) =\u003e console.log('two'));\n\nconst snap = abettor.snapshot('myEvent', 'emit');\n\nabettor.on('myEvent', (my, arguments) =\u003e console.log('three'));\n\n// All three subscribed on's are triggered \nabettor.emit('myEvent');\n\n// Only the first two  subscribed on's are triggered three is not\nsnap();\n```\n\n\n\n---\n\nBest, te","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffetchte%2Fabettor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffetchte%2Fabettor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffetchte%2Fabettor/lists"}