message-port-api
Version:
A simple package that allows you to simplify the use of `MessagePort API` more easily (Worker, IFrame...)
122 lines (120 loc) • 3.95 kB
JavaScript
;
(() => {
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/index.ts
function isRequest(data) {
return data && "id" in data && "arguments" in data;
}
function isResponseResult(data) {
return data && "id" in data && "result" in data;
}
function isResponseError(data) {
return data && "id" in data && "error" in data;
}
function useValue(value) {
return typeof value === "function" ? value() : value;
}
function useReceive(sender, receiver) {
if (!receiver && "postMessage" in sender)
receiver = sender;
const handlers = /* @__PURE__ */ new Set();
function receive(controllers, targetOrigin) {
function handler(_0) {
return __async(this, arguments, function* ({ data }) {
if (isRequest(data)) {
if (data.name in controllers) {
const controller = controllers[data.name];
try {
const responseResult = {
id: data.id,
name: data.name,
result: yield controller(...data.arguments)
};
useValue(receiver).postMessage(responseResult, targetOrigin);
} catch (err) {
const responseError = {
id: data.id,
name: data.name,
error: err + ""
};
useValue(receiver).postMessage(responseError, targetOrigin);
}
} else {
const responseError = {
id: data.id,
name: data.name,
error: "NOT_FOUND_ERR"
};
useValue(receiver).postMessage(responseError, targetOrigin);
}
}
});
}
useValue(sender).addEventListener("message", handler);
handlers.add(handler);
return controllers;
}
receive.cancel = () => {
const senderVal = useValue(sender);
handlers.forEach((handler) => {
senderVal.removeEventListener("message", handler);
});
};
return receive;
}
function useSend(sender, receiver, timeout = 3e4) {
if (!receiver && "postMessage" in sender)
receiver = sender;
function send(name, args, targetOrigin) {
const id = Math.random().toString(34).slice(2);
return new Promise(
(resolve, reject) => {
const request = {
id,
name,
arguments: args
};
useValue(sender).addEventListener("message", handler);
const timer = !timeout ? void 0 : setTimeout(() => {
reject("TIME_OUT");
useValue(sender).removeEventListener("message", handler);
}, timeout);
function handler({ data }) {
if (isResponseResult(data) && data.id === id && data.name === name) {
timer && clearTimeout(timer);
resolve(data.result);
useValue(sender).removeEventListener("message", handler);
return;
}
if (isResponseError(data) && data.id === id && data.name === name) {
timer && clearTimeout(timer);
reject(data.error);
useValue(sender).removeEventListener("message", handler);
}
}
useValue(receiver).postMessage(request, targetOrigin);
}
);
}
return send;
}
})();