{"id":18563167,"url":"https://github.com/compulim/event-as-promise","last_synced_at":"2025-04-10T03:32:38.657Z","repository":{"id":31106329,"uuid":"126903437","full_name":"compulim/event-as-promise","owner":"compulim","description":"Handle continuous steam of events in Promise fashion","archived":false,"fork":false,"pushed_at":"2025-02-12T00:14:27.000Z","size":495,"stargazers_count":3,"open_issues_count":2,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-08T07:45:31.690Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/compulim.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-26T23:51:42.000Z","updated_at":"2024-12-06T13:06:39.000Z","dependencies_parsed_at":"2024-06-18T21:11:55.640Z","dependency_job_id":"db2c347f-3c0f-406f-a6b1-59b42e36ea54","html_url":"https://github.com/compulim/event-as-promise","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/compulim%2Fevent-as-promise","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/compulim%2Fevent-as-promise/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/compulim%2Fevent-as-promise/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/compulim%2Fevent-as-promise/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/compulim","download_url":"https://codeload.github.com/compulim/event-as-promise/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248151381,"owners_count":21056084,"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-06T22:11:57.935Z","updated_at":"2025-04-10T03:32:37.920Z","avatar_url":"https://github.com/compulim.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# event-as-promise\n\nHandle continuous stream of events with Promise and generator function.\n\n[![npm version](https://badge.fury.io/js/event-as-promise.svg)](https://npmjs.com/package/event-as-promise)\n\nInstead of listen to event *just once*, `event-as-promise` chose an approach to allow listening to the same event continuously. And we support *generator function* to enable `for await (const data of eventAsPromise)` loop to handle event indefinitely.\n\n# Breaking changes\n\n## 2.0.0\n\nWe moved default imports to named imports:\n\n```diff\n- import EventAsPromise from 'event-as-promise';\n+ import { EventAsPromise } from 'event-as-promise';\n```\n\nWe removed `options: { array: boolean }`, to receive all arguments from Node.js event emitter:\n\n```diff\n- target.on(eventAsPromise.eventListener);\n+ target.on((...args) =\u003e eventAsPromise.eventListener(args));\n```\n\nOnly `eventListener` is bound to the instance of `EventAsPromise`. Other functions (`one` and `upcoming`) are not bound and will need to be call in the context of `EventAsPromise`. If you want to call it bound:\n\n```diff\n  const eventAsPromise = new EventAsPromise();\n- const one = eventAsPromise.one;\n+ const one = eventAsPromise.one.bind(eventAsPromise)\n\n  button.addEventListener('click', eventAsPromise.eventListener);\n\n  await one();\n```\n\n# How to use\n\n## Web server\n\nThis sample code is converted from [Node about page](https://nodejs.org/en/about/).\n\n```js\nimport { EventAsPromise } from 'event-as-promise';\nimport http from 'http';\n\nasync function main(ready) {\n  const server = http.createServer();\n  const listeningPromises = new EventAsPromise();\n  const requestPromises = new EventAsPromise();\n\n  server\n    .once('listening', listeningPromises.eventListener)\n    .on('request', (...args) =\u003e requestPromises.eventListener(args))\n    .listen(3000);\n\n  // Wait for \"listening\"\n  await listeningPromises.one();\n\n  // Loop indefinitely, using generator\n  for (let requestPromise of requestPromises) {\n    // Wait for \"request\"\n    const [req, res] = await requestPromise;\n\n    res.statusCode = 200;\n    res.setHeader('Content-Type', 'text/plain');\n    res.end('Hello World\\n');\n  }\n}\n\nmain();\n```\n\n## Redux Saga\n\nHandling event in a Promise may not reduce complexity. But it will be beneficial for [`redux-saga`](https://redux-saga.js.org/) when mixed with [`call`](https://redux-saga.js.org/docs/api/#callfn-args) effect.\n\nIn this example, when the user is connected via `CONNECTED` action, we will keep the user posted about file changes, until a `DISCONNECTED` is received.\n\n```js\nsaga.run(function* () {\n  yield takeLatest('CONNECTED', function* (action) {\n    const watcher = fs.watch(action.payload);\n    const changePromises = new EventAsPromise();\n\n    watcher.on('change', changePromises.eventListener);\n\n    for (;;) {\n      const changes = yield race([\n        call(changePromises.one),\n        take('DISCONNECTED'),\n      ]);\n\n      if (changes) {\n        yield put({ type: 'CHANGED', payload: changes });\n      } else {\n        break;\n      }\n    }\n\n    watcher.close();\n  });\n});\n```\n\n## Futures\n\nYou can retrieve multiple Promise objects before the event is emitted.\n\n```js\nconst emitter = new EventEmitter();\nconst countPromises = new EventAsPromise();\n\nemitter.on('count', countPromises.eventListener);\n\n// Retrieve multiple future Promise before the actual event is fired\nconst promise1 = countPromises.one();\nconst promise2 = countPromises.one();\nconst promise3 = countPromises.one();\n\nemitter.emit('count', 1);\nemitter.emit('count', 2);\nemitter.emit('count', 3);\n\nawait expect(promise1).resolves.toBe(1);\nawait expect(promise2).resolves.toBe(2);\nawait expect(promise3).resolves.toBe(3);\n```\n\n\u003e Same as event listener, if `one()` is not called before the event is emitted, the event will be lost.\n\n## Upcomings\n\nInstead of futures, you can use `upcoming()` to get the Promise for the upcoming event. Futures and upcoming Promises are independent of each other, as shown in the sample below.\n\n```js\nconst emitter = new EventEmitter();\nconst countPromises = new EventAsPromise();\n\nemitter.on('count', countPromises.eventListener);\n\nconst promiseOne1 = countPromises.upcoming();\nconst promiseOne2 = countPromises.upcoming();\nconst promiseOne3 = countPromises.one();\nconst promiseTwo = countPromises.one();\n\nemitter.emit('count', 'one');\nemitter.emit('count', 'two');\n\nawait expect(promiseOne1).resolves.toBe('one');\nawait expect(promiseOne2).resolves.toBe('one');\nawait expect(promiseOne3).resolves.toBe('one');\nawait expect(promiseTwo).resolves.toBe('two');\n\nconst promiseThree = countPromises.upcoming();\n\nemitter.emit('count', 'three');\n\nawait expect(promiseOne1).resolves.toBe('one');\nawait expect(promiseThree).resolves.toBe('three');\n```\n\n\u003e Note: after the current `upcoming()` has resolved, you will need to call `upcoming()` again to obtain a new Promise for the next upcoming event.\n\n# Contributions\n\nLike us? [Star](https://github.com/compulim/event-as-promise/stargazers) us.\n\nWant to make it better? [File](https://github.com/compulim/event-as-promise/issues) us an issue.\n\nDon't like something you see? [Submit](https://github.com/compulim/event-as-promise/pulls) a pull request.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcompulim%2Fevent-as-promise","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcompulim%2Fevent-as-promise","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcompulim%2Fevent-as-promise/lists"}