Skip to content

Commit

Permalink
Update TypeScript types to allow listeners that return Promises
Browse files Browse the repository at this point in the history
Emittery already supports awaiting event emission, which in turn awaits all the listeners that return a Promise. If a caller awaits `emit`, all the listeners will have resolved by the time the outer promise resolves, which is great!

This adds a test for that behaviour, and updates the TypeScript types to support these async listeners. There's no new or changed behaviour.
  • Loading branch information
airhorns committed Dec 28, 2020
1 parent 809522a commit f9cca0f
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 6 deletions.
12 changes: 6 additions & 6 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,11 +144,11 @@ declare class Emittery<
*/
on<Name extends keyof EventData>(
eventName: Name,
listener: (eventData: EventData[Name]) => void
listener: (eventData: EventData[Name]) => void | Promise<void>
): Emittery.UnsubscribeFn;
on(
eventName: typeof Emittery.listenerAdded | typeof Emittery.listenerRemoved,
listener: (eventData: Emittery.ListenerChangedData) => void
listener: (eventData: Emittery.ListenerChangedData) => void | Promise<void>
): Emittery.UnsubscribeFn;

/**
Expand Down Expand Up @@ -263,7 +263,7 @@ declare class Emittery<
*/
off<Name extends keyof EventData>(
eventName: Name,
listener: (eventData: EventData[Name]) => void
listener: (eventData: EventData[Name]) => void | Promise<void>
): void;

/**
Expand Down Expand Up @@ -328,7 +328,7 @@ declare class Emittery<
listener: (
eventName: keyof EventData,
eventData: EventData[keyof EventData]
) => void
) => void | Promise<void>
): Emittery.UnsubscribeFn;

/**
Expand Down Expand Up @@ -376,7 +376,7 @@ declare class Emittery<
listener: (
eventName: keyof EventData,
eventData: EventData[keyof EventData]
) => void
) => void | Promise<void>
): void;

/**
Expand Down Expand Up @@ -429,7 +429,7 @@ declare namespace Emittery {
/**
The listener that was added or removed.
*/
listener: (eventData?: unknown) => void;
listener: (eventData?: unknown) => Promise<void>;

/**
The name of the event that was added or removed if `.on()` or `.off()` was used, or `undefined` if `.onAny()` or `.offAny()` was used.
Expand Down
15 changes: 15 additions & 0 deletions index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,20 @@ import Emittery = require(".");
expectError(ee.on("value", (value: number) => {}));
}

// Async listeners
{
const ee = new Emittery<{
open: undefined;
close: string
}>();
ee.on("open", () => {});
ee.on("open", async () => {});
ee.on("open", () => Promise.resolve());
ee.on("close", async (value) => {
expectType<string>(value)
});
}

// Strict typing for onAny, offAny listeners
{
const ee = new Emittery<{
Expand Down Expand Up @@ -137,3 +151,4 @@ import Emittery = require(".");
}
};
}

15 changes: 15 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,21 @@ test.cb('emit() - is async', t => {
t.false(unicorn);
});

test('emit() - awaits async listeners', async t => {
const emitter = new Emittery();
let unicorn = false;

emitter.on('🦄', async () => {
await Promise.resolve();
unicorn = true;
});

const promise = emitter.emit('🦄');
t.false(unicorn);
await promise;
t.true(unicorn);
});

test('emit() - calls listeners subscribed when emit() was invoked', async t => {
const emitter = new Emittery();
const calls = [];
Expand Down

0 comments on commit f9cca0f

Please sign in to comment.