Simple promise based post message / listener.
import { onMessage } from '@2k/post-message';
const cb = async (msg) => {
console.log(msg.oid, msg.origin, msg.data)
// wait some async operation
const resp = await foo(msg.data);
return resp;
}
// source: all
const unSub_all = onMessage(cb);
const unSub_star = onMessage('*', cb);
// source: window
const unSub_1 = onMessage(
window.parent,
cb
);
// source: iframe
const unSub_2 = onMessage(
document.getElementById('iframe'),
cb // callback
);
// source: iframe.contentWindow
const unSub_3 = onMessage(
document.getElementById('iframe').contentWindow,
cb
);
import { sendMessage } from '@2k/post-message';
// target: window
const resp_1 = await sendMessage(
window.parent,
{ name: 'foo' },
{
needResponse: true,
timeout: 10000 // response timeout
}
);
console.log(resp_1.result)
// target: iframe
const resp_2 = await sendMessage(
document.getElementById('iframe')
{ name: 'bar' },
);
console.log(resp_2.result)
// target: iframe.contentWindow
const resp_3 = await sendMessage(
document.getElementById('iframe').contentWindow
{ name: 'baz' },
);
console.log(resp_3.result)
<!-- bridge.html--->
<script src="https://unpkg.com/@2k/post-message"></script>
<iframe id="iframeA" src="https://a.com/a.tml"></iframe>
<iframe id="iframeB" src="https://b.com/b.html"></iframe>
<script>
const {onMessage, sendMessage} = twoK
const iframeA = document.getElementById("iframeA");
const iframeB = document.getElementById("iframeB");
onMessage(iframeA, (msg) => sendMessage(iframeB, msg.data));
onMessage(iframeB, (msg) => sendMessage(iframeA, msg.data));
</script>
<!-- https://a.com/a.tml--->
<input id="input" type="text" value="a" onkeyup="send()">
<script>
const {onMessage, sendMessage} = twoK
onMessage(parent, async (msg) => {
document.getElementById('input').value = msg.data
return `A received : ${msg.data}`
})
async function send() {
const value = document.getElementById('input').value
const [err, res] = await sendMessage(parent, value, {
needResponse: true,
timeout: 1000
}).then(res => [null, res], (err) => [err])
console.log(['A send done', err, res?.result])
}
</script>
<!-- https://b.com/b.html--->
<input id="input" type="text" value="b" onkeyup="send()">
<script>
const {onMessage, sendMessage} = twoK
onMessage(parent, async (msg) => {
document.getElementById('input').value = msg.data
return `B received : ${msg.data}`
})
async function send() {
const value = document.getElementById('input').value
const [err, res] = await sendMessage(parent, value, {
needResponse: true,
timeout: 1000
}).then(res => [null, res], (err) => [err])
console.log(['B send done', err, res?.result])
}
</script>
type Endpoint = 'parent' | 'child';
type SendOptions = {
origin?: string;
endpoint?: Endpoint;
needsResponse?: boolean;
timeout?: number;
};
type MsgBody<T> = {
oid: number;
data: T;
ctime: number;
origin?: string;
};
type MsgResp<T> = {
oid: number;
result: T;
ctime: number;
};
type MsgCb<T, R> = (msg: MsgBody<T>) => Promise<R> | R;
/**
* Listen to messages from a source frame.
*
* @param { function } cb - optional source frame, listens to all messages if not provided.
* @returns { function } - unsubscribe function
*/
declare function onMessage<T, R>(cb: MsgCb<T, R>): () => boolean;
/**
* Listen to messages from a source frame.
*
* @param { HTMLIFrameElement | Window | '*' | function } source - optional source frame, listens to all messages if not provided.
* @param { function } cb - callback function
* @returns { function } - unsubscribe function
*/
declare function onMessage<T, R>(
source: HTMLIFrameElement | Window | '*',
cb: MsgCb<T, R>): () => boolean;
/**
* Listen to messages from a source DOM Node.
*
* @param { HTMLElement } source - optional source frame, listens to all messages if not provided.
* @param { function } cb
* @param { "parent" | "child" } endpoint
* @returns { function } - unsubscribe function
*/
declare function onMessage<T, R>(
source: HTMLElement,
cb: MsgCb<T, R>,
endpoint: Endpoint): () => boolean;
/**
* Send messages to a target frame or DOM node.
*
* @param { HTMLIFrameElement | HTMLElement | Window } target - The target window | iframe | DOM node
* @param { * } data - The message payload
* @param { SendOptions } options - The options
* @returns { Promise<Response> } - Response
*/
declare function sendMessage<T, R>(
target: HTMLIFrameElement | HTMLElement | Window,
data: T,
options?: SendOptions): Promise<MsgResp<Awaited<R>>>;