Skip to content

Commit

Permalink
Add "emitLast" option support (#32)
Browse files Browse the repository at this point in the history
* add the declaration

* add saving the last value

* add sendign last event

* adding condition

* use lastEvent property

* refactoring

* adding test for lastValue

* adding issue reference
  • Loading branch information
vitaly-t authored Sep 29, 2024
1 parent 3e14f71 commit 6588884
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 11 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sub-events",
"version": "1.9.1",
"version": "1.10.0",
"description": "Lightweight, strongly-typed events, with monitored subscriptions.",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
Expand Down
38 changes: 29 additions & 9 deletions src/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,16 @@ export interface ISubscriber<T> extends ISubContext<T> {
*/
export class SubEvent<T = unknown> {

/**
* Last emitted event, if there was any, or `undefined` otherwise.
*
* It is set after all subscribers have received the event, but just before
* optional {@link IEmitOptions.onFinished} callback is invoked.
*/
get lastEvent(): T | undefined {
return this._lastEvent;
}

/**
* @hidden
*/
Expand All @@ -226,6 +236,12 @@ export class SubEvent<T = unknown> {
*/
protected _subs: ISubscriber<T>[] = [];

/**
* Last emitted event container.
* @private
*/
private _lastEvent?: T;

/**
* Event constructor.
*
Expand Down Expand Up @@ -282,11 +298,11 @@ export class SubEvent<T = unknown> {
}
cb = options && 'thisArg' in options ? cb.bind(options.thisArg) : cb;
const cancel = () => {
if (options && typeof options.onCancel === 'function') {
if (typeof options?.onCancel === 'function') {
options.onCancel();
}
};
const name = options && options.name;
const name = options?.name;
const sub: ISubscriber<T> = {event: this, cb, name, cancel};
if (typeof this.options.onSubscribe === 'function') {
const ctx: ISubContext<T> = {event: sub.event, name: sub.name, data: sub.data};
Expand Down Expand Up @@ -318,7 +334,7 @@ export class SubEvent<T = unknown> {
public once(cb: SubFunction<T>, options?: ISubOptions): Subscription {
const sub = this.subscribe((data: T) => {
sub.cancel();
return cb.call(options && options.thisArg, data);
return cb.call(options?.thisArg, data);
}, options);
return sub;
}
Expand All @@ -328,7 +344,7 @@ export class SubEvent<T = unknown> {
* which is synchronous by default.
*
* @param data
* Data to be sent, according to the template type.
* Event data to be sent, according to the template type.
*
* @param options
* Event-emitting options.
Expand All @@ -340,9 +356,9 @@ export class SubEvent<T = unknown> {
if (typeof (options ?? {}) !== 'object') {
throw new TypeError(Stat.errInvalidOptions);
}
const schedule: EmitSchedule = (options && options.schedule) ?? EmitSchedule.sync;
const onFinished = options && typeof options.onFinished === 'function' && options.onFinished;
const onError = options && typeof options.onError === 'function' && options.onError;
const schedule: EmitSchedule = options?.schedule ?? EmitSchedule.sync;
const onFinished = typeof options?.onFinished === 'function' && options.onFinished;
const onError = typeof options?.onError === 'function' && options.onError;
const start = schedule === EmitSchedule.sync ? Stat.callNow : Stat.callNext;
const middle = schedule === EmitSchedule.async ? Stat.callNext : Stat.callNow;
start(() => {
Expand All @@ -360,8 +376,12 @@ export class SubEvent<T = unknown> {
} else {
sub.cb && sub.cb(data);
}
if (onFinished && index === r.length - 1) {
onFinished(r.length); // finished sending
if (index === r.length - 1) {
// the end of emission reached;
this._lastEvent = data; // save the last event
if (onFinished) {
onFinished(r.length); // notify
}
}
}));
});
Expand Down
20 changes: 20 additions & 0 deletions test/event.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -457,3 +457,23 @@ describe('toConsumer', () => {
expect((c as any).cancelAll).to.be.undefined;
});
});

describe('lastEvent', () => {
it('must be set once emission finished', done => {
const e = new SubEvent<number>();
e.subscribe(dummy); // TODO: Should not be needed with #33 is resolved?

const onFinished = (count: number) => {
expect(e.lastEvent).to.eq(123);
};

const handler = chai.spy(onFinished);
e.emit(123, {onFinished: handler, schedule: EmitSchedule.async});
expect(e.lastEvent).to.be.undefined;

setTimeout(() => {
expect(handler).to.have.been.called.with(1);
done();
});
});
});
2 changes: 1 addition & 1 deletion typedoc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "https://typedoc.org/schema.json",
"name": "SUB-EVENTS v1.9.1",
"name": "SUB-EVENTS v1.10.0",
"out": "./docs",
"excludeExternals": true,
"excludePrivate": true,
Expand Down

0 comments on commit 6588884

Please sign in to comment.