{"id":24427439,"url":"https://github.com/re-quant/rxjs-awaitable-observables","last_synced_at":"2026-04-12T19:48:01.590Z","repository":{"id":42794810,"uuid":"272589021","full_name":"Re-Quant/rxjs-awaitable-observables","owner":"Re-Quant","description":"🧨  This package makes async/await working with Observables without .toPromise() 💥","archived":false,"fork":false,"pushed_at":"2023-03-05T00:36:29.000Z","size":960,"stargazers_count":2,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-04-25T21:44:44.599Z","etag":null,"topics":["angular","async-await","nestjs","promise","rxjs","ts","typescript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Re-Quant.png","metadata":{"files":{"readme":"README.md","changelog":null,"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}},"created_at":"2020-06-16T02:16:52.000Z","updated_at":"2022-01-25T17:36:52.000Z","dependencies_parsed_at":"2023-02-05T18:30:56.875Z","dependency_job_id":"47ff960d-c6a2-4404-94a2-49c55aaef0f8","html_url":"https://github.com/Re-Quant/rxjs-awaitable-observables","commit_stats":null,"previous_names":["re-quant/rxjs-awaitable-observables","z-brain/rxjs-awaitable-observables"],"tags_count":10,"template":false,"template_full_name":"korniychuk/wallaby-ts-starter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Re-Quant%2Frxjs-awaitable-observables","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Re-Quant%2Frxjs-awaitable-observables/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Re-Quant%2Frxjs-awaitable-observables/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Re-Quant%2Frxjs-awaitable-observables/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Re-Quant","download_url":"https://codeload.github.com/Re-Quant/rxjs-awaitable-observables/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243447513,"owners_count":20292448,"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":["angular","async-await","nestjs","promise","rxjs","ts","typescript"],"created_at":"2025-01-20T12:10:40.822Z","updated_at":"2025-12-25T19:56:09.132Z","avatar_url":"https://github.com/Re-Quant.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RxJS Awaitable Observables\n\n\u003cp align=\"center\"\u003e\n  \u003ca target=\"_blank\" href=\"https://github.com/z-brain/rxjs-awaitable-observables/actions?query=workflow%3A%22Build%22\"\u003e\n    \u003cimg alt=\"Build status\" src=\"https://github.com/z-brain/rxjs-awaitable-observables/workflows/Build/badge.svg\"\u003e\n  \u003c/a\u003e\n  \u003ca target=\"_blank\" href=\"https://www.npmjs.com/package/@z-brain/rxjs-awaitable-observables\"\u003e\n    \u003cimg alt=\"NPM version\" src=\"https://img.shields.io/npm/v/@z-brain/rxjs-awaitable-observables.svg\"\u003e\n  \u003c/a\u003e\n  \u003ca target=\"_blank\" href=\"https://codecov.io/gh/z-brain/rxjs-awaitable-observables\"\u003e\n    \u003cimg alt=\"Code Coverage\" src=\"https://codecov.io/gh/z-brain/rxjs-awaitable-observables/branch/master/graph/badge.svg\"\u003e\n  \u003c/a\u003e\n  \u003ca target=\"_blank\" href=\"https://www.gnu.org/licenses/gpl-3.0\"\u003e\n    \u003cimg alt=\"License: GPL v3\" src=\"https://img.shields.io/badge/License-GPLv3-blue.svg\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e🧨 \u0026nbsp;\u0026nbsp; 💥 \u0026nbsp;\u0026nbsp; 💪 \u0026nbsp;\u0026nbsp; \u003cstrong\u003eUse async/await with any RxJS stream and be happy\u003c/strong\u003e \u0026nbsp;\u0026nbsp; ✅ \u0026nbsp;\u0026nbsp; 👨‍💻 \u0026nbsp;\u0026nbsp; 😎\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\u003ci\u003eZero third-party dependencies\u003c/i\u003e\u003c/p\u003e\n\n\u003cp\u003e\u0026nbsp;\u003c/p\u003e\n\u003cp\u003e\u003ci\u003eNotice: If you have any propositions feel free to make an issue or create a pull request.\u003c/i\u003e\u003c/p\u003e\n\n![IDE Demo](/resources/ide-demo.png)\n\n## Installation\n\n### 1. Install the package\n\n`yarn add @z-brain/rxjs-awaitable-observables`  \nor  \n`npm i -s @z-brain/rxjs-awaitable-observables`\n\n### 2. Add the import line of the package to your entry .ts files\n\nYour `main.ts`:\n```typescript\nimport '@z-brain/rxjs-awaitable-observables';\n```\n\nThat is all 🙂\u0026nbsp; Feel free to use async/await with observables 😉\n\n**Detailed description:**\n\n* In case of Angular project it can be `main.ts`\n* In case of a server project it is the entry file of your server app (`index.ts` or `server.ts` in most cases)\n\n### 3. Configure you testing framework\n\nIf you are going to use async/await with observables in any kind of your tests (unit / e2e) there are two ways to do it:  \n\n1. Add a setup file with the import to you testing framework. In case of `Jest` it can be done via `setupFiles` or `setupFilesAfterEnv`. **(recommended)**\n\n  ```javascript\n  // jest.config.js\n  module.exports = {\n  ...\n  setupFiles: [ './jest.setup.ts' ],\n  ...\n  };\n  \n  // jest.setup.ts\n  import '@z-brain/rxjs-awaitable-observables';\n  ```\n2. Or you can manually import the package to each of your test **(unrecommended)**\n\n## Usage examples\n\n**1. Simple example: async/await works with completed observables**\n\n```typescript\nconst value$ = $$.of(123);\nconst value = await value$;\nexpect(value).toBe(123);\n```\n\n**2. Take the first value in the stream**\n```typescript\nconst value$: Observable\u003cnumber\u003e = $$.of(111, 222, 333);\nconst value = await value$;\nexpect(value).toBe(111);\n```\n\n**3. Takes the last value of a completed stream**\n```typescript\nconst value$: Observable\u003cnumber\u003e = $$.of(111, 222, 333);\nconst value = await value$.pipe($.last());\nexpect(value).toBe(333);\n```\n\n**4. Take the initial value of `Subject` + `.startWith()`**\n```typescript\n      const newValues$: Observable\u003cnumber\u003e = new Subject\u003cnumber\u003e();\n      const value$ = newValues$.pipe($.startWith(123));\n\n      const value = await value$;\n      expect(value).toBe(123);\n```\n\n**5. Take the first value of `ReplaySubject`**\n```typescript\nconst value$ = new ReplaySubject\u003cnumber\u003e(2);\nvalue$.next(111);\nvalue$.next(222);\nvalue$.next(333);\nvalue$.next(444);\n\nconst value = await value$;\n\nexpect(value).toBe(333);\n```\n\n**6. Error handling using try/catch**\n```typescript\nconst MSG = 'Something went wrong';\nconst err$ = $$.throwError(new Error(MSG));\n\ntry {\n  await err$;\n} catch (e) {\n  expect(e.message).toMatch(MSG);\n}\n```\n\n**7. throw an EmptyError on completing observable without a message**\n```typescript\nconst emptyStream$ = $$.EMPTY;\n\ntry {\n    await emptyStream$;\n} catch (e) {\n    expect(e).toBeInstanceOf(EmptyError);\n}\n```\n\n**8. Manually .then() call (Promises integration)**\n```typescript\nconst value$: Observable\u003cnumber\u003e = $$.of(123);\n\nconst promise = Promise.resolve(10)\n                       .then(multiplier =\u003e value$.then(v =\u003e v * multiplier));\n\nreturn expect(promise).resolves.toBe(1230);\n```\n\n## How does it work?\n\n* This package patches `Observables`'s prototype and adds `.then()` method to make all `Observable`s and its children work with `async`/`await` as is without the necessary to call `.toPromise()`\n* Yes, the package patches .prototype of another package (RxJS).  \n  In theory, it can be dangerous. However, this package does it enough carefully.  \n  We already saw some successful examples of patching .prototype even build-in functions. (Zone.js for example)  \n  I suggest don't afraid and make our daily work easier and our code more beautiful.\n\n**100% test coverage**:  \n```\nasync/await tests\n  ✅ async/await should work with completed observables\n  ✅ Should take the first value in the stream\n  ✅ Should take the last value of a completed stream\n  ✅ Should take the current value of BehaviorSubject\n  ✅ Should take the initial value of Subject + .startWith()\n  ✅ Should take the first value of ReplaySubject\n  ✅ try/catch should handle an error from the stream via async/await\n  ✅ Should throw an EmptyError on completing observable without message\nCheck integration with Promises\n  ✅ Should work with manually .then() call\n  ✅ Empty .then() call should just return a promise with the value without any errors\n  ✅ In case of error in the stream empty .then() call should do nothing and return rejected promise with the error\n\n```\n\n## Development notes\n\n### Quick Start\n\n```bash\ncd /code/z-brain\ngit clone git@github.com:z-brain/rxjs-awaitable-observables.git\ncd rxjs-awaitable-observables\nyarn install\n```\n\n### How to use NodeJS version from the `.nvmrc`\n\n1. Install NVM\n2. Use `.nvmrc` file one of the next ways:\n\n    * Execute `nvm use` in the project root directory\n    * Install [NVM Loader](https://github.com/korniychuk/ankor-shell) and your .nvmrc will be loaded automatically when you open the terminal.\n      ![NVM Loader demo](./resources/readme.nvm-loader.png)\n\n### How to make a build\n\n`npm run build`\n\n### How to run lint\n\n* Just show problems `npm run lint`\n* Fix problems if it is possible `npm run lint:fix`\n\n### How to run tests\n\n* All tests\n\n  `npm run test`  \n  `npm run test:watch`\n* Specific tests\n\n  `npm run test -- src/my.spec.ts`  \n  `npm run test:watch -- src/my.spec.ts`\n\n### How to build and publish NPM package\n\n*NPM Token:* `3240...1349`\n\nCI configuration details here: [.github/workflows/npmpublish.yml](.github/workflows/npmpublish.yml)\n\n```bash\nnpm run pre-push\n\u0026\u0026 npm version patch -m 'Update package version version to %s'\n\u0026\u0026 npm run gen-public-package.json\n\u0026\u0026 cp README.md dist/\n\u0026\u0026 npm publish dist --access public\n\u0026\u0026 git push --no-verify \u0026\u0026 git push --tags --no-verify\n```\n\n### How to build package to local installation\n\n1. `yarn run build:local`\n2. Then you can install a local package build from path `file:.../rxjs-awaitable-observables/dist`.\n\n## Author\n\n| [\u003cimg src=\"https://www.korniychuk.pro/avatar.jpg\" width=\"100px;\"/\u003e\u003cbr /\u003e\u003csub\u003eAnton Korniychuk\u003c/sub\u003e](https://korniychuk.pro) |\n| :---: |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fre-quant%2Frxjs-awaitable-observables","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fre-quant%2Frxjs-awaitable-observables","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fre-quant%2Frxjs-awaitable-observables/lists"}