Skip to content

Instantly share code, notes, and snippets.

@bramblex
Last active June 16, 2020 13:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bramblex/db9c760c36d60442e20d28782a701221 to your computer and use it in GitHub Desktop.
Save bramblex/db9c760c36d60442e20d28782a701221 to your computer and use it in GitHub Desktop.
/* eslint-disable */
/*
一套基于 postMessage 的页面间通讯协议
*/
/*
interface Request {
id: number
type: 'req'
message: {
type: string,
data: any
}
}
interface Response {
id: number
type: 'res'
message: {
ok: bool
data: any
}
}
*/
function uuid() {
let dt = new Date().getTime();
let uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
let r = (dt + Math.random() * 16) % 16 | 0;
dt = Math.floor(dt / 16);
return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
});
return uuid;
}
export class PostIO {
constructor(clientWindow, origin) {
this._clientId = uuid();
this._handlers = {};
this._requests = {};
this._clientWindow = clientWindow;
this._origin = origin || '*';
window.addEventListener('message', (event) => {
const data = event.data;
if (data && data.id && data.type && data.message && data.client) {
const {type, client} = data;
if (client === this._clientId) {
return;
} else if (type === 'req') {
this._onRequest(data);
} else if (type === 'res') {
this._onResponse(data);
}
}
}, false);
}
_onRequest(data) {
const {id, message} = data;
const {type} = message;
const handler = this._handlers[type];
if (!handler) {
this._response(id, false, `method "${type}" not found`);
} else {
try {
const result = handler(message.data);
if (result && result.then && result.catch) {
result.then(data => this._response(id, true, data));
result.catch(err => this._response(id, false, err));
} else {
this._response(id, true, result);
}
} catch (err) {
this._response(id, false, err);
}
}
}
_onResponse(data) {
const {id, message} = data;
if (this._requests[id]) {
const [resolve, reject] = this._requests[id];
delete this._requests[id];
message.ok ? resolve(message.data) : reject(message.data);
}
}
_response(id, ok, data) {
this._clientWindow.postMessage({
id, client: this._clientId, type: 'res', message: {ok, data},
}, this._origin);
}
handle(type, handler) {
this._handlers[type] = handler;
return this;
}
request(type, data) {
const promise = new Promise((resolve, reject) => {
const id = uuid();
const req = {
id,
client: this._clientId,
type: 'req',
message: {
type: type,
data: data,
},
};
this._requests[id] = [resolve, reject];
this._clientWindow.postMessage(req, this._origin);
});
return promise;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment