@fcanvas/communicate
v1.1.7
Published
This package allows a simple connection between MessageChannel-based channels such as WebWorker
Downloads
173
Maintainers
Readme
@fcanvas/communicate
This package allows a simple connection between MessageChannel-based channels such as WebWorker
, IFrame
...
View source code at: https://github.com/fcanvas/fcanvas
Install
pnpm add @fcanvas/communicate
Usage
With MessageChannel
// listen run function
import { listen } from "@fcanvas/communicate"
const { port1, port2 } = new MessageChannel()
port1.start()
port2.start()
listen(port1, "hello world", (name: string) => {
console.log(`run: hello world '${name}'`)
return "run done"
})
// call function
import { put } from "@fcanvas/communicate"
console.log(await put(port2, "hello world", "Shin")) // "run done"
With WebWorker
worker.ts
import { listen } from "@fcanvas/communicate"
listen(self, "hello world", (name: string) => {
console.log(`run: hello world '${name}'`)
return "run done"
})
main.ts
import Worker from "./worker?worker"
import { put } from "@fcanvas/communicate"
const worker = new Worker()
console.log(await put(worker, "hello world", "Shin")) // "run done"
2-way use
You can use both ways set listen
to Worker
or Threat
worker.ts
import { listen } from "@fcanvas/communicate"
listen(self, "hello world", async (name: string) => {
console.log(`run: hello world '${name}'`)
console.log("input: ", await put(self, "get input"))
return "run done"
})
main.ts
import Worker from "./worker?worker"
import { put } from "@fcanvas/communicate"
const worker = new Worker()
listen(worker, "get input", () => {
return document.querySelector("#input").value
})
console.log(await put(worker, "hello world", "Shin")) // "run done"
Docs
@fcanvas/communicate
provides 3 methods that can be used anywhere
listen
This function to listen and process calls from put
and pit
- like is server
function listen(
port: LikeMessagePort, // current port to listen and process. Example `self` in `worker`
name: string, // the name of the listen
cb: Function, // its handler function takes a sequence of `arguments` passed from `put` or `pit` and returns a result either a `config` or a `promise`
options?: {
once?: boolean // if this option is enabled the listener will self-destruct after being called once by `put` or `pit`
}
): StopListen/** @type () => void */
| Name | Type | Description |
| --- | --- | --- |
| port | LikeMessagePort | Current port to listen and process. Example self
in worker
|
| name | string | The name of the listen |
| cb | Function | Its handler function takes a sequence of arguments
passed from put
or pit
and returns a result either a config
or a Promise
| options | { once?: boolean } | if once: true
is enabled the listener will self-destruct after being called once by put
or pit
cb
normally returns primitive values but if it returns a value that needstransfer
likeOffscreen
orArrayBuffer
return anOptions
interface Options { return: any // your value return transfer?: Transferable[] // value transfer targetOrigin?: string // This option is only available if communicating with `IFrame` }
listen(self, "get buffer", async () => { const buffer = new Uint8Array([1, 0xf, 0x3]).buffer return { return: buffer, transfer: [buffer] } })
listen
returns anoop
function that, when called, cancels listening
put
This function sends a request to listen
and returns a promise
that is the result of cb
of listen
-
like is client
function put<Fn extends (...args: any[]) => any>(
port: LikeMessagePort, // current port to listen and process. Example `self` in `worker`
name: string, // name of call
...args: Parameters<Fn>
): Promise<ReturnType<Fn>>
function put<Fn extends (...args: any[]) => any>(
port: LikeMessagePort, // current port to listen and process. Example `self` in `worker`
options: {
name: string // name of call
timeout?: number // timeout
signal?: AbortSignal, // controller
transfer?: Transferable[], // value transfer
targetOrigin?: string // This option is only available if communicating with `IFrame`
},
...args: Parameters<Fn>
): Promise<ReturnType<Fn>>
| Name | Type | Description |
| --- | --- | ---- |
| port | LikeMessagePort | Current port to listen and process. Example self
in worker
|
| name | string | name of call |
| options.name | string | is like name
| options.timeout | number? | timeout listen
returns a result. if timeout without response will generate error Error('timeout')
|
| options.signal | AbortSignal? | if canceled the function will generate an error Error('aborted')
|
| options.transfer | Transferable[]? | values to transfer
|
| options.targetOrigin | string? | This option is only available if communicating with IFrame
|
| ...args | any[] | values to send to listen
|
put
returns the value thatcb
oflisten
returns
pit
(as ping
)
This is a shortened function of put
that takes no response. it also doesn't care if the call has been sent to listen
or not
The options of this function are identical to put
except that it does not accept options.timeout
, option.signal
and returns nothing.
wait
This function waits for a call from ping
or put
await wait(port1, "ready", 60_000)
console.log("Done")
//
await put(port2, "ready") // after promise resolve console.log("Done") start run
TypeScript
This plugin also supports TypeScript strong and weak type inference
Weak inference with function
:
interface FnHello {
(name: string): string
}
listen<FnHello>(self, "hello", (name /** @type string */) => {
return 'done' /** @type string */
})
put<FnHello>(self, "hello", "Shin") // ✔ ok
put<FnHello>(self, "hello", 0) // ❗ error
Strong inference with Record
:
interface Connect {
hello(name: string): void
}
listen<Connect>("self", "hello", () => {}) // ✔ ok
listen<Connect>("self", "hellx", () => {}) // ❗ error
put<Connect>(self, "hello", "Shin") // ✔ ok
put<Connect>(self, "hello", 0) // ❗ error
put<Connect>(self, "hello") // ❗ error
put<Connect>(self, "hellx", "Shin") // ❗ error
Since some limited features of typescript cause mixed types to be incorrect, I have added a new syntax i.e. put
, ping
and listen
functions will return a function call after calling the function that will be the real result
await put<{
getValue(): string
getNumber(): number
setValue(val: string): void
setNumber(val: number): void
}>(self)("getValue") // string
await put<{
getValue(): string
getNumber(): number
setValue(val: string): void
setNumber(val: number): void
}>(self)("setValue", "Hello world") // only accept string
listen<{
getValue(): string
getNumber(): number
setValue(val: string): void
setNumber(val: number): void
}>(self)("getValue", () => {
return "hello" // accept string
})
listen<{
getValue(): string
getNumber(): number
setValue(val: string): void
setNumber(val: number): void
}>(self)("setValue", value => {
// value is string
})
Copyright
MIT - (c) 2022-now Tachibana Shin (橘しん)