rpc.ts 1.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. export namespace Rpc {
  2. type Definition = {
  3. [method: string]: (input: any) => any
  4. }
  5. export function listen(rpc: Definition) {
  6. onmessage = async (evt) => {
  7. const parsed = JSON.parse(evt.data)
  8. if (parsed.type === "rpc.request") {
  9. const result = await rpc[parsed.method](parsed.input)
  10. postMessage(JSON.stringify({ type: "rpc.result", result, id: parsed.id }))
  11. }
  12. }
  13. }
  14. export function client<T extends Definition>(target: {
  15. postMessage: (data: string) => void | null
  16. onmessage: ((this: Worker, ev: MessageEvent<any>) => any) | null
  17. }) {
  18. const pending = new Map<number, (result: any) => void>()
  19. let id = 0
  20. target.onmessage = async (evt) => {
  21. const parsed = JSON.parse(evt.data)
  22. if (parsed.type === "rpc.result") {
  23. const resolve = pending.get(parsed.id)
  24. if (resolve) {
  25. resolve(parsed.result)
  26. pending.delete(parsed.id)
  27. }
  28. }
  29. }
  30. return {
  31. call<Method extends keyof T>(method: Method, input: Parameters<T[Method]>[0]): Promise<ReturnType<T[Method]>> {
  32. const requestId = id++
  33. return new Promise((resolve) => {
  34. pending.set(requestId, resolve)
  35. target.postMessage(JSON.stringify({ type: "rpc.request", method, input, id: requestId }))
  36. })
  37. },
  38. }
  39. }
  40. }