util.ts 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839
  1. import { GlobalBus, type GlobalEvent } from "@/bus/global"
  2. import { Effect } from "effect"
  3. export function waitEvent(input: { timeout: number; signal?: AbortSignal; fn: (event: GlobalEvent) => boolean }) {
  4. if (input.signal?.aborted) return Effect.fail(input.signal.reason ?? new Error("Request aborted"))
  5. return Effect.callback<void, unknown>((resume) => {
  6. const abort = () => {
  7. cleanup()
  8. resume(Effect.fail(input.signal?.reason ?? new Error("Request aborted")))
  9. }
  10. const handler = (event: GlobalEvent) => {
  11. try {
  12. if (!input.fn(event)) return
  13. cleanup()
  14. resume(Effect.void)
  15. } catch (error) {
  16. cleanup()
  17. resume(Effect.fail(error))
  18. }
  19. }
  20. const cleanup = () => {
  21. clearTimeout(timeout)
  22. GlobalBus.off("event", handler)
  23. input.signal?.removeEventListener("abort", abort)
  24. }
  25. const timeout = setTimeout(() => {
  26. cleanup()
  27. resume(Effect.fail(new Error("Timed out waiting for global event")))
  28. }, input.timeout)
  29. GlobalBus.on("event", handler)
  30. input.signal?.addEventListener("abort", abort, { once: true })
  31. return Effect.sync(cleanup)
  32. })
  33. }