优化iframe内使用的优化
This commit is contained in:
155
src/_export.js
155
src/_export.js
@@ -10,37 +10,23 @@ import {
|
||||
resolveUseParentProxy,
|
||||
} from "./services/embedProxy";
|
||||
import { createUUID } from "./utils/uuid";
|
||||
import { dispatchHardwareScanResult } from "./services/provider/scan";
|
||||
import { startScanner, stopScanner } from "./services/scanner";
|
||||
import {
|
||||
dispatchEmbedScanResult,
|
||||
acknowledgeEmbedScanConsumed,
|
||||
} from "./services/provider/scan";
|
||||
import { setEmbedScanResultForwarder } from "./services/embedScanBridge";
|
||||
|
||||
const EMBED_SOURCE = "IScanEmbed";
|
||||
const EMBED_V = 1;
|
||||
|
||||
/** 嵌入子页已注册的监听 key(与父页监听对应,用于 refcount 决定是否在本页挂载扫码枪按键监听) */
|
||||
const childEmbedScanGunKeys = new Set();
|
||||
/** offScanListener(fn) 时反查对应的 key */
|
||||
const embedScanGunWeakListenerKey = new WeakMap();
|
||||
/** 已向父页发起过 invoke 的嵌入子 frame(用于父页识别结果回传) */
|
||||
const embedChildSources = new Set();
|
||||
|
||||
function syncEmbedScanGunForwardFromChild() {
|
||||
if (typeof window === "undefined" || !resolveUseParentProxy()) {
|
||||
return;
|
||||
}
|
||||
if (childEmbedScanGunKeys.size === 0) {
|
||||
stopScanner();
|
||||
return;
|
||||
}
|
||||
startScanner((result) => {
|
||||
window.parent.postMessage(
|
||||
{
|
||||
source: EMBED_SOURCE,
|
||||
v: EMBED_V,
|
||||
kind: "forwardScanGun",
|
||||
result,
|
||||
},
|
||||
"*"
|
||||
);
|
||||
});
|
||||
}
|
||||
const EMBED_LISTENER_METHODS = new Set([
|
||||
"onScanListener",
|
||||
"offScanListener",
|
||||
"clear",
|
||||
]);
|
||||
|
||||
function isEmbedMessage(data) {
|
||||
return data && data.source === EMBED_SOURCE && data.v === EMBED_V;
|
||||
@@ -119,36 +105,24 @@ function hydrateEmbedParams(params, messageSource, targetOrigin) {
|
||||
return params.map(walk);
|
||||
}
|
||||
|
||||
function serializeEmbedInvokeResult(methodKey, result) {
|
||||
if (
|
||||
methodKey === "onScanListener" &&
|
||||
result &&
|
||||
typeof result === "object" &&
|
||||
typeof result.key === "string"
|
||||
) {
|
||||
return { __IScanEmbedListenerRef__: true, key: result.key };
|
||||
function broadcastScanResultToEmbedChildren(result) {
|
||||
if (embedChildSources.size === 0 || result == null || result === "") {
|
||||
return;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function deserializeEmbedInvokeResult(methodKey, raw) {
|
||||
if (
|
||||
methodKey === "onScanListener" &&
|
||||
raw &&
|
||||
raw.__IScanEmbedListenerRef__ &&
|
||||
typeof raw.key === "string"
|
||||
) {
|
||||
const key = raw.key;
|
||||
return {
|
||||
key,
|
||||
cancel: () => {
|
||||
childEmbedScanGunKeys.delete(key);
|
||||
syncEmbedScanGunForwardFromChild();
|
||||
embedInvoke("offScanListener", [key]).catch(() => {});
|
||||
},
|
||||
};
|
||||
}
|
||||
return raw;
|
||||
embedChildSources.forEach((source) => {
|
||||
try {
|
||||
source.postMessage(
|
||||
{
|
||||
source: EMBED_SOURCE,
|
||||
v: EMBED_V,
|
||||
kind: "forwardScanResult",
|
||||
result,
|
||||
},
|
||||
"*"
|
||||
);
|
||||
} catch (e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
let embedWxProbeScheduled = false;
|
||||
@@ -207,6 +181,23 @@ function embedChildOnMessage(ev) {
|
||||
setParentWxEnvReport(!!data.wx);
|
||||
return;
|
||||
}
|
||||
if (data.kind === "forwardScanResult") {
|
||||
if (typeof data.result === "string") {
|
||||
const consumed = dispatchEmbedScanResult(data.result);
|
||||
if (consumed && resolveUseParentProxy()) {
|
||||
window.parent.postMessage(
|
||||
{
|
||||
source: EMBED_SOURCE,
|
||||
v: EMBED_V,
|
||||
kind: "scanResultConsumed",
|
||||
result: data.result,
|
||||
},
|
||||
"*"
|
||||
);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (data.kind === "invokeResult") {
|
||||
const pending = pendingInvokes[data.id];
|
||||
if (!pending) {
|
||||
@@ -214,7 +205,7 @@ function embedChildOnMessage(ev) {
|
||||
}
|
||||
delete pendingInvokes[data.id];
|
||||
if (data.ok) {
|
||||
pending.resolve(deserializeEmbedInvokeResult(data.methodKey, data.result));
|
||||
pending.resolve(data.result);
|
||||
} else {
|
||||
pending.reject(new Error(data.error || "[IScan embed]: invoke failed"));
|
||||
}
|
||||
@@ -277,7 +268,6 @@ function handleEmbedHostInvoke(lib, ev) {
|
||||
return out;
|
||||
})
|
||||
.then((result) => {
|
||||
const serializedResult = serializeEmbedInvokeResult(methodKey, result);
|
||||
ev.source.postMessage(
|
||||
{
|
||||
source: EMBED_SOURCE,
|
||||
@@ -286,7 +276,7 @@ function handleEmbedHostInvoke(lib, ev) {
|
||||
id,
|
||||
methodKey,
|
||||
ok: true,
|
||||
result: serializedResult,
|
||||
result,
|
||||
},
|
||||
ev.origin
|
||||
);
|
||||
@@ -316,6 +306,7 @@ export function installEmbedHost(lib) {
|
||||
return;
|
||||
}
|
||||
embedHostInstalled = true;
|
||||
setEmbedScanResultForwarder(broadcastScanResultToEmbedChildren);
|
||||
window.addEventListener("message", (ev) => {
|
||||
const data = ev.data;
|
||||
if (!isEmbedMessage(data)) {
|
||||
@@ -338,15 +329,13 @@ export function installEmbedHost(lib) {
|
||||
);
|
||||
return;
|
||||
}
|
||||
/** 嵌入子页焦点下扫码枪的 keydown:子页转成字符串后透出,再走主页面监听与嵌入回调链路 */
|
||||
if (data.kind === "forwardScanGun") {
|
||||
if (data.kind === "scanResultConsumed") {
|
||||
if (!ev.source || ev.source === window) {
|
||||
return;
|
||||
}
|
||||
if (typeof data.result !== "string") {
|
||||
return;
|
||||
if (typeof data.result === "string") {
|
||||
acknowledgeEmbedScanConsumed(data.result);
|
||||
}
|
||||
dispatchHardwareScanResult(data.result);
|
||||
return;
|
||||
}
|
||||
if (data.kind !== "invoke") {
|
||||
@@ -358,6 +347,7 @@ export function installEmbedHost(lib) {
|
||||
if (!ev.source || ev.source === window) {
|
||||
return;
|
||||
}
|
||||
embedChildSources.add(ev.source);
|
||||
handleEmbedHostInvoke(lib, ev);
|
||||
});
|
||||
}
|
||||
@@ -420,42 +410,11 @@ function freezeObj(obj) {
|
||||
function createInvokeTransport(lib, method, methodName, initNames) {
|
||||
return function IScanInvokeProxy(...params) {
|
||||
if (resolveUseParentProxy()) {
|
||||
if (methodName === "onScanListener") {
|
||||
const listener = params[0];
|
||||
const key = params[1];
|
||||
if (!key || typeof key !== "string" || typeof listener !== "function") {
|
||||
return;
|
||||
if (EMBED_LISTENER_METHODS.has(methodName)) {
|
||||
if (!isReadyCalled() && initNames && initNames.indexOf(method) < 0) {
|
||||
throw `[IScan]:Can't call the "IScan.${method}" method, because "IScan" not ready, please confirm that "IScan.ready()" has been called. params: ${JSON.stringify(params)}`
|
||||
}
|
||||
embedScanGunWeakListenerKey.set(listener, key);
|
||||
childEmbedScanGunKeys.add(key);
|
||||
syncEmbedScanGunForwardFromChild();
|
||||
embedInvoke(methodName, params).catch(() => {});
|
||||
return {
|
||||
key,
|
||||
cancel: () => {
|
||||
childEmbedScanGunKeys.delete(key);
|
||||
syncEmbedScanGunForwardFromChild();
|
||||
embedInvoke("offScanListener", [key]).catch(() => {});
|
||||
},
|
||||
};
|
||||
}
|
||||
if (methodName === "offScanListener") {
|
||||
const p0 = params[0];
|
||||
if (typeof p0 === "string") {
|
||||
childEmbedScanGunKeys.delete(p0);
|
||||
} else if (typeof p0 === "function") {
|
||||
const rk = embedScanGunWeakListenerKey.get(p0);
|
||||
if (rk != null && rk !== "") {
|
||||
childEmbedScanGunKeys.delete(rk);
|
||||
}
|
||||
}
|
||||
syncEmbedScanGunForwardFromChild();
|
||||
return embedInvoke(methodName, params);
|
||||
}
|
||||
if (methodName === "clear") {
|
||||
childEmbedScanGunKeys.clear();
|
||||
syncEmbedScanGunForwardFromChild();
|
||||
return embedInvoke(methodName, params);
|
||||
return _exec(lib, methodName, ...params);
|
||||
}
|
||||
return embedInvoke(methodName, params);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user