版博士V2.0程序
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

README.md 2.6 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. # @tootallnate/once
  2. ### Creates a Promise that waits for a single event
  3. ## Installation
  4. Install with `npm`:
  5. ```bash
  6. $ npm install @tootallnate/once
  7. ```
  8. ## API
  9. ### once(emitter: EventEmitter, name: string, opts?: OnceOptions): Promise<[...Args]>
  10. Creates a Promise that waits for event `name` to occur on `emitter`, and resolves
  11. the promise with an array of the values provided to the event handler. If an
  12. `error` event occurs before the event specified by `name`, then the Promise is
  13. rejected with the error argument.
  14. ```typescript
  15. import once from '@tootallnate/once';
  16. import { EventEmitter } from 'events';
  17. const emitter = new EventEmitter();
  18. setTimeout(() => {
  19. emitter.emit('foo', 'bar');
  20. }, 100);
  21. const [result] = await once(emitter, 'foo');
  22. console.log({ result });
  23. // { result: 'bar' }
  24. ```
  25. #### Promise Strong Typing
  26. The main feature that this module provides over other "once" implementations is that
  27. the Promise that is returned is _**strongly typed**_ based on the type of `emitter`
  28. and the `name` of the event. Some examples are shown below.
  29. _The process "exit" event contains a single number for exit code:_
  30. ```typescript
  31. const [code] = await once(process, 'exit');
  32. // ^ number
  33. ```
  34. _A child process "exit" event contains either an exit code or a signal:_
  35. ```typescript
  36. const child = spawn('echo', []);
  37. const [code, signal] = await once(child, 'exit');
  38. // ^ number | null
  39. // ^ string | null
  40. ```
  41. _A forked child process "message" event is type `any`, so you can cast the Promise directly:_
  42. ```typescript
  43. const child = fork('file.js');
  44. // With `await`
  45. const [message, _]: [WorkerPayload, unknown] = await once(child, 'message');
  46. // With Promise
  47. const messagePromise: Promise<[WorkerPayload, unknown]> = once(child, 'message');
  48. // Better yet would be to leave it as `any`, and validate the payload
  49. // at runtime with i.e. `ajv` + `json-schema-to-typescript`
  50. ```
  51. _If the TypeScript definition does not contain an overload for the specified event name, then the Promise will have type `unknown[]` and your code will need to narrow the result manually:_
  52. ```typescript
  53. interface CustomEmitter extends EventEmitter {
  54. on(name: 'foo', listener: (a: string, b: number) => void): this;
  55. }
  56. const emitter: CustomEmitter = new EventEmitter();
  57. // "foo" event is a defined overload, so it's properly typed
  58. const fooPromise = once(emitter, 'foo');
  59. // ^ Promise<[a: string, b: number]>
  60. // "bar" event in not a defined overload, so it gets `unknown[]`
  61. const barPromise = once(emitter, 'bar');
  62. // ^ Promise<unknown[]>
  63. ```
  64. ### OnceOptions
  65. - `signal` - `AbortSignal` instance to unbind event handlers before the Promise has been fulfilled.