{"id":26502854,"url":"https://github.com/grassator/happened","last_synced_at":"2025-03-20T18:35:58.491Z","repository":{"id":30522737,"uuid":"34077244","full_name":"grassator/happened","owner":"grassator","description":"PubSub / Event Bus library","archived":false,"fork":false,"pushed_at":"2016-10-18T08:28:07.000Z","size":20,"stargazers_count":10,"open_issues_count":0,"forks_count":4,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-08-10T21:34:16.246Z","etag":null,"topics":["event-bus","events","pubsub"],"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/grassator.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":"2015-04-16T19:54:11.000Z","updated_at":"2023-07-31T07:06:54.000Z","dependencies_parsed_at":"2022-08-17T20:21:28.928Z","dependency_job_id":null,"html_url":"https://github.com/grassator/happened","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grassator%2Fhappened","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grassator%2Fhappened/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grassator%2Fhappened/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grassator%2Fhappened/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/grassator","download_url":"https://codeload.github.com/grassator/happened/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244671973,"owners_count":20491282,"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":["event-bus","events","pubsub"],"created_at":"2025-03-20T18:35:57.594Z","updated_at":"2025-03-20T18:35:58.470Z","avatar_url":"https://github.com/grassator.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# happened\n\n[![NPM version](https://badge.fury.io/js/happened.svg)](https://npmjs.org/package/happened)\n[![GitHub version][git-tag-image]][project-url]\n[![Build Status][travis-image]][travis-url]\n[![Dependency Status][daviddm-url]][daviddm-image]\n\n\n`happened` is a tiny PubSub library (~700 bytes minified and gzipped). It's designed to have a minimal viable set of features, making it an ideal choice for using in your own library or size-sensitive client code.\n\n## Examples\n\n`happened` does not try include any unnecessary functionality in the core, but that doesn't mean that it's hard to use in all the common cases.\n\n### Basic usage\n\nCalling `happened.create()` without any parameters will  construct a new instance, that can be used as an event bus:\n\n```js\nvar happened = require('happened');\nvar topSecretMessages = happened.create();\ntopSecretMessages.on('mission', function (type) {\n    console.log('completed mission ' + type);\n});\ntopSecretMessages.trigger('mission', 'impossible'); // \"completed mission impossible\"\n```\n\nThis can also work as global event bus — just wrap it in a requirable module:\n\n```js\n// my-global-bus.js\nvar happened = require('happened');\nmodule.exports = happened.create();\n\n// my-other-file.js\nvar globalBus = require('./my-global-bus');\nglobalBus.on('disco', function () {\n    console.log('dance');\n});\nglobalBus.trigger('disco'); // \"dance\"\n```\n\n### Mixin for Objects\n\nIt's a very common need to have PubSub methods directly exposed on some object, or all objects of a given class. This is usually solved by providing a mixin (e.g. Backbone.Events), which has a downside of a need to define a property on an object, that can conflict with your own properties, or even cause compiler deoptimization if it's injected dynamically by `on` method.\n\nAll the methods on `happened` instance can be called in any context, so that means that they can be simply copied in the constructor of your class:\n\n```js\nvar happened = require('happened');\n\nfunction Artist() {\n    var events = happened.create();\n    // you can choose which methods to copy from happened\n    this.on = events.on;\n    this.once = events.once;\n    this.off = events.off;\n    this.trigger = events.trigger;\n    \n    // additionally if you want to provide support to subscribe\n    // to all events it's a good idea to copy corresponding constant\n    this.ALL_EVENTS = events.ALL_EVENTS;\n}\n\nvar superMetalBand = new Artist();\nsuperMetalBand.on('concert', function () {\n    console.log('scream');\n});\nsuperMetalBand.trigger('concert'); // \"scream\"\n```\n\nSince this is quite verbose `happened` provides a helper method for this common case:\n\n```js\nfunction Artist() {\n    happened.addTo(this);\n}\n```\n\n### Public Channels\n\nThe basic implementation of public channels is to return the same instance of `happened`, given the same string, representing the name of the channel, which is exactly what more general [memoization](http://en.wikipedia.org/wiki/Memoization) function does, which is available for example in [lodash](https://lodash.com/docs#memoize):\n\n```js\nvar happened = require('happened');\nvar _ = require('lodash');\nvar channel = _.memoize(happened.create);\n\nvar radioOne = channel('radio1');\nradio1.on('morning-broadcast', function () {\n    console.log('wake up');\n});\n\n// in another place\nchannel('radio1').trigger('morning-broadcast'); // \"wake up\"\n```\n\nIf you want to keep dependencies minimal it's also easy to write it yourself:\n\n```js\nvar channel = (function () {\n    var cache = {};\n    return function (name) {\n        return cache.hasOwnProperty(name) ? cache[name] : (cache[name] = happened.create());\n    };\n})();\n```\n\n\u003e At this point you are probably wondering why this is not included in the library itself. There are a couple of reasons for this. Firstly this is not an essential functionality that would be required for every use case. But more importantly, since `happened.create()` can accept `options` argument specifying a custom scheduler (and may be some other options later on), there is no way to unambiguously tell what would be the result of theoretical `happened.channel('one', options) === happened.channel('one', options2)`.\n\n## More Good Stuff\n\n* Zero dependencies\n* Minimal interface (`on`, `once`, `off`, `trigger`), with utility methods exposed only on a global object. \n* UMD package\n* Support for custom schedulers.\n* Support for legacy browsers like IE6-8 and Android 2.3\n* Node.js support\n* all `happened` instances are [frozen](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze) (immutable) if supported by environment\n\n## Requirements\n\n`happened` by default uses asynchronous event dispatching. If you want events to be dispatched faster, you can use `scheduler` option in `happened.create` call to specify other schedulers, such as [setImmediate](https://github.com/YuzuJS/setImmediate) for macro-task behavior or `process.nextTick` for micro-tasks.\n\nDefault async (setTimeout) mode is supported for all mainstream browsers and Node.js, but may not work in some esoteric environments, like [Qt QML](http://doc.qt.io/qt-5/qtqml-javascript-hostenvironment.html). In this case it falls back to synchronous scheduler.\n\nIf you want to always create instance of `happened` with sync scheduler, you can create a simple proxy function:\n\n```js\nfunction createSyncEvents() {\n    return happened.create({ scheduler: happened.SYNC });\n}\n```\n\n## API\n\nThis section contains reference for all public methods and properties of `happened`, to see example usage please refer to [examples section](#usage-patterns) instead.\n\nType signatures for methods are presented using [flow](http://flowtype.org/docs/functions.html) syntax.\n\n### Top-Level Library Methods and Properties\n\n#### `happened.create()`\n\nConstructs a new [instance](#instance-methods) of `happened`.\n\n```js\nhappened.create(options : Object?) =\u003e HappenedInstance\n```\n\nRight now the only supported field in `options` is `scheduler`:\n\n```\nvar nextTickBus = happened.create({ scheduler: process.nextTick.bind(process) });\n```\n\n#### `happened.addTo()`\n\nThis is convenience method to create a new instance of `happened` and copy it's methods `on`, `once`, `off`, `trigger` and a constant `ALL_EVENTS` to a given `target`:\n\n```js\nhappened.addTo(target : Object, source : HappenedInstance?) =\u003e HappenedInstance\n```\n\nCalling this function without a `source` will create a new instance of `happened`, but you can also provide one in case you want to share event bus between several object or you want to use an instance with custom scheduler:\n\n```\nvar foo = {};\nhappened.addTo(foo, happened.create({ scheduler: happened.SYNC }));\n```\n\n### Instance Methods\n\n#### `on`\n\nThis method is used to subscribe for a certain event:\n\n```js\nhappenedInstance.on(\n    name     : string,\n    callback : (...params) =\u003e void,\n    thisArg  : Object?\n) =\u003e void\n```\n\nThe `callback` will receive all the parameters except for the name of the event from `trigger` as it's arguments. `thisArg` is optional context for callback.\n\nSpecial case here is subscribing to all events, happening on the instance. To do this you need to provide `ALL_EVENTS` constant property available on all instances.\n\n```js\nhappenedInstance.on(\n    happened.ALL_EVENTS,\n    callback : (name : string, params : Array\u003cany\u003e) =\u003e void,\n    thisArg  : Object?\n) =\u003e void\n```\n\n\u003e NOTE: `callback` for all events has a different signature to a regular one, due to a need to pass event name.\n\n#### `once`\n\nSame as [`on`](#on), but causes the `callback` to only fire once before being `off`ed.\n\n```js\nhappenedInstance.once(\n    name     : string,\n    callback : (...params) =\u003e void,\n    thisArg  : Object?\n) =\u003e void\n```\n\n#### `off`\n\nRemoves a specific `callback` for an event with a given `name`.\n\n```js\nhappenedInstance.off(\n    name     : string?,\n    callback : Function?\n) =\u003e void\n```\n\nIf called without `callback`, removes all callbacks for given `name`.\n\nIf called without any arguments, remove all callbacks for all events.\n\n#### `trigger`\n\nTriggers callbacks for the given event `name`, additional `...params` to `trigger` will be passed along to the event callbacks.\n\n```js\nhappenedInstance.trigger(\n    name      : string,\n    ...params : any\n) =\u003e void\n```\n\n## Contributing\n\n### Setting Up Development Environment\n\nTo start do a fork of this repo, clone it locally and type in your terminal:\n\n```bash\nnpm install\ngulp tdd\n```\n\nThis will continuously run tests for nice dev experience. To run tests just once or in CI environment you can use:\n\n```bash\ngulp test\n```\n\nTo build for production run:\n\n```bash\ngulp build\n```\n\n## License\n\n© 2015 Dmitriy Kubyshkin. Licensed under the MIT style license.\n\n[project-url]: https://github.com/grassator/happened\n[git-tag-image]: http://img.shields.io/github/tag/grassator/happened.svg\n[travis-url]: https://travis-ci.org/grassator/happened\n[travis-image]: https://travis-ci.org/grassator/happened.svg?branch=master\n[daviddm-url]: https://david-dm.org/grassator/happened.svg?theme=shields.io\n[daviddm-image]: https://david-dm.org/grassator/happened\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrassator%2Fhappened","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgrassator%2Fhappened","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrassator%2Fhappened/lists"}