asyncBus.ts 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  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. console.log(fn)
  46. await fn(args)
  47. }
  48. }
  49. }
  50. },
  51. }
  52. return bus
  53. }