Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: merge Ready and EventEmitter #5

Merged
merged 2 commits into from
Dec 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ name: CI
on:
push:
branches: [ master ]

pull_request:
branches: [ master ]

Expand All @@ -12,5 +11,7 @@ jobs:
name: Node.js
uses: node-modules/github-actions/.github/workflows/node-test.yml@master
with:
version: '16.17.0, 16, 18, 20'
version: '16.17.0, 16, 18, 20, 22'
os: 'ubuntu-latest'
secrets:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
2 changes: 0 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,3 @@ jobs:
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
with:
checkTest: false
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[![CI](https://github.com/node-modules/get-ready/actions/workflows/nodejs.yml/badge.svg)](https://github.com/node-modules/get-ready/actions/workflows/nodejs.yml)
[![Test coverage][codecov-image]][codecov-url]
[![npm download][download-image]][download-url]
[![Node.js Version](https://img.shields.io/node/v/get-ready.svg?style=flat)](https://nodejs.org/en/download/)

[npm-image]: https://img.shields.io/npm/v/get-ready.svg?style=flat-square
[npm-url]: https://npmjs.org/package/get-ready
Expand Down Expand Up @@ -51,6 +52,16 @@ obj.ready(true);
obj.ready().then(() => console.log('ready'));
```

### ReadyEventEmitter

```ts
import { ReadyEventEmitter } from 'get-ready';

class MyClass extends ReadyEventEmitter {
// your handler here
}
```

**Warning: the callback is called after nextTick**

### Emit
Expand Down Expand Up @@ -79,13 +90,8 @@ obj.ready(new Error('err'));

[MIT](LICENSE)

<!-- GITCONTRIBUTOR_START -->

## Contributors

|[<img src="https://avatars.githubusercontent.com/u/221826?v=4" width="100px;"/><br/><sub><b>supershabam</b></sub>](https://github.com/supershabam)<br/>|[<img src="https://avatars.githubusercontent.com/u/156269?v=4" width="100px;"/><br/><sub><b>fengmk2</b></sub>](https://github.com/fengmk2)<br/>|[<img src="https://avatars.githubusercontent.com/u/360661?v=4" width="100px;"/><br/><sub><b>popomore</b></sub>](https://github.com/popomore)<br/>|[<img src="https://avatars.githubusercontent.com/u/985607?v=4" width="100px;"/><br/><sub><b>dead-horse</b></sub>](https://github.com/dead-horse)<br/>|[<img src="https://avatars.githubusercontent.com/u/32174276?v=4" width="100px;"/><br/><sub><b>semantic-release-bot</b></sub>](https://github.com/semantic-release-bot)<br/>|
| :---: | :---: | :---: | :---: | :---: |

This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Mon Jun 05 2023 14:06:50 GMT+0800`.
[![Contributors](https://contrib.rocks/image?repo=node-modules/get-ready)](https://github.com/node-modules/get-ready/graphs/contributors)

<!-- GITCONTRIBUTOR_END -->
Made with [contributors-img](https://contrib.rocks).
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,14 @@
"egg-bin": "^6.4.1",
"eslint": "^8.51.0",
"eslint-config-egg": "^13.0.0",
"git-contributor": "^2.1.5",
"tshy": "^1.2.2",
"tshy": "3",
"tshy-after": "^1.0.0",
"typescript": "^5.2.2"
},
"engines": {
"node": ">= 16.13.0"
},
"scripts": {
"contributor": "git-contributor",
"lint": "eslint src test --ext ts",
"test": "npm run lint && egg-bin test",
"ci": "egg-bin cov && npm run prepublishOnly && npm pack",
Expand Down Expand Up @@ -65,5 +63,7 @@
}
},
"type": "module",
"types": "./dist/commonjs/index.d.ts"
"types": "./dist/commonjs/index.d.ts",
"main": "./dist/commonjs/index.js",
"module": "./dist/esm/index.js"
}
29 changes: 24 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { EventEmitter } from 'node:events';

export type CallbackFunction = (err?: Error) => void;
export type ReadyFunctionArg = boolean | Error | CallbackFunction | undefined;
export type ReadyFunctionArg = boolean | Error | CallbackFunction;

export class Ready {
#isReady: boolean;
Expand All @@ -11,6 +13,8 @@ export class Ready {
this.#readyCallbacks = [];
}

ready(): Promise<void>;
ready(flagOrFunction: ReadyFunctionArg): void;
ready(flagOrFunction?: ReadyFunctionArg) {
// register a callback
if (flagOrFunction === undefined || typeof flagOrFunction === 'function') {
Expand All @@ -25,7 +29,7 @@ export class Ready {
* It will return promise when no argument passing.
*/
#register(func?: CallbackFunction) {
// support `this.ready().then(onready);` and `await this.ready()`;
// support `this.ready().then(onReady);` and `await this.ready()`;
if (!func) {
return new Promise<void>((resolve, reject) => {
function func(err?: Error) {
Expand All @@ -51,8 +55,8 @@ export class Ready {
}

/**
* Call the callbacks that has been registerd, and clean the callback stack.
* If the flag is not false, it will be marked as ready. Then the callbacks will be called immediatly when register.
* Call the callbacks that has been registered, and clean the callback stack.
* If the flag is not false, it will be marked as ready. Then the callbacks will be called immediately when register.
* @param {Boolean|Error} flag - Set a flag whether it had been ready. If the flag is an error, it's also ready, but the callback will be called with argument `error`
*/
#emit(flag: boolean | Error) {
Expand All @@ -76,8 +80,23 @@ export class Ready {
if (!obj) return;
const ready = new Ready();
// delegate method
obj.ready = (flagOrFunction: any) => ready.ready(flagOrFunction);
obj.ready = (flagOrFunction: any) => {
return ready.ready(flagOrFunction);
};
}
}

export default Ready;

export class ReadyEventEmitter extends EventEmitter {
#readyObj = new Ready();

ready(): Promise<void>;
ready(flagOrFunction: ReadyFunctionArg): void;
ready(flagOrFunction?: ReadyFunctionArg) {
if (flagOrFunction === undefined) {
return this.#readyObj.ready();
}
this.#readyObj.ready(flagOrFunction);
}
}
49 changes: 42 additions & 7 deletions test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { strict as assert } from 'node:assert';
import Ready, { ReadyFunctionArg, Ready as ReadyBase } from '../src/index.js';
import Ready, { ReadyFunctionArg, Ready as ReadyBase, ReadyEventEmitter } from '../src/index.js';

class SomeClass {
property: string;
Expand All @@ -10,8 +10,13 @@ class SomeClass {
this.#readyObject = new Ready();
}

ready(): Promise<void>;
ready(arg: ReadyFunctionArg): void;
ready(arg?: ReadyFunctionArg) {
return this.#readyObject.ready(arg);
if (arg === undefined) {
return this.#readyObject.ready();
}
this.#readyObject.ready(arg);
}

method() {
Expand All @@ -32,6 +37,22 @@ class ReadySubClass extends ReadyBase {
}
}

class ReadyEventClass extends ReadyEventEmitter {
property: string;

constructor() {
super();
this.property = 'value';
this.ready(() => {
this.emit('ready-event');
});
}

method() {
return 'method';
}
}

describe('Ready.mixin', () => {
it('should exports mixin', () => {
assert(Ready.mixin);
Expand Down Expand Up @@ -88,7 +109,7 @@ describe('new Ready()', () => {
assert.deepEqual(arr, [ 1, 2 ]);
});

it('should immediatly call callback when already ready', done => {
it('should immediately call callback when already ready', done => {
const someClass = new SomeClass();
someClass.ready(true);
someClass.ready(done);
Expand All @@ -113,11 +134,25 @@ describe('new Ready()', () => {
});
});

describe('new ReadyEventClass()', () => {
it('should have Ready properties', async () => {
const someClass = new ReadyEventClass();
assert('ready' in someClass);
let gotReadyEvent = false;
someClass.on('ready-event', () => {
gotReadyEvent = true;
});
someClass.ready(true);
await someClass.ready();
assert.equal(gotReadyEvent, true);
});
});

describe('promise', () => {
it('should resolve after ready', done => {
const someClass = new SomeClass();
someClass.ready()!.then(() => {
someClass.ready()!.then(done);
someClass.ready().then(() => {
someClass.ready().then(done);
});
someClass.ready(true);
});
Expand All @@ -144,7 +179,7 @@ describe('error', () => {

it('should get error in promise', done => {
const someClass = new SomeClass();
someClass.ready()!.catch(err => {
someClass.ready().catch(err => {
assert(err);
assert(err.message === 'error');
done();
Expand All @@ -165,7 +200,7 @@ describe('error', () => {
it('should get error after ready in promise', done => {
const someClass = new SomeClass();
someClass.ready(new Error('error'));
someClass.ready()!.catch(err => {
someClass.ready().catch(err => {
assert(err);
assert(err.message === 'error');
done();
Expand Down
Loading