asyncBus.ts 2.0 KB

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