useAsyncBus.ts 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. const Pre = '__pre__'
  2. const Last = '__last__'
  3. export type Handler<T = unknown> = (event: T) => any
  4. export type Events = Record<string, unknown>
  5. export type Flush = { pre?: boolean; last?: boolean }
  6. export type Bus<T extends Events> = {
  7. on<Key extends keyof T>(
  8. type: Key,
  9. handler: Handler<T[Key]>,
  10. flush?: Flush
  11. ): void
  12. off<Key extends keyof T>(
  13. type: Key,
  14. handler?: Handler<T[Key]>,
  15. flush?: Flush
  16. ): void
  17. emit<Key extends keyof T>(type: Key, args?: T[Key]): Promise<any>
  18. }
  19. export const useAsyncBus = <T extends Events>() => {
  20. const store = {} as { [key in keyof T]: Array<Handler> }
  21. const allKey = (type): Array<keyof T> => [Pre + type, type, Last + type]
  22. const getKey = (type, flush: Flush): keyof T => {
  23. const keys = allKey(type)
  24. return flush
  25. ? flush.pre
  26. ? keys[0]
  27. : flush.last
  28. ? keys[2]
  29. : keys[0]
  30. : keys[0]
  31. }
  32. const bus: Bus<T> = {
  33. on: (type, handler, flush) => {
  34. const key = getKey(type, flush)
  35. if (!store[key]) {
  36. store[key] = []
  37. }
  38. if (!store[key].includes(handler)) {
  39. store[key].push(handler)
  40. }
  41. },
  42. off: (type, handler, flush) => {
  43. const keys = flush ? [getKey(type, flush)] : allKey(type)
  44. for (const key of keys) {
  45. if (handler) {
  46. if (store[key]) {
  47. store[key] = store[key].filter(h => h !== handler)
  48. }
  49. } else if (store[key]) {
  50. delete store[key]
  51. }
  52. }
  53. },
  54. emit: async (type, args) => {
  55. const keys = allKey(type)
  56. for (const key of keys) {
  57. if (store[key]) {
  58. for (const fn of store[key]) {
  59. await fn(args)
  60. }
  61. }
  62. }
  63. }
  64. }
  65. return bus
  66. }