捕获使用srcDoc属性定义的iframe中的JavaScript错误

bhmjp9jg  于 2023-06-04  发布在  Java
关注(0)|答案(2)|浏览(128)

我正在创建一个React组件,它使用srcDoc属性在iframe集合中呈现任意HTML/JavaScript。然而,iframe可能有可能有错误的脚本,我想在这种情况下显示错误消息而不是iframe。然而,错误的触发似乎非常不一致,我推测是由于时间问题。如何确保错误处理程序被触发?

const RenderHtml = ({ htmlBlock }: { htmlBlock: HtmlBlock }) => {
  const iframeRef = useRef<HTMLIFrameElement>(null);
  const [hasError, setHasError] = useState<boolean>(false);

  useEffect(() => {
    if (!iframeRef.current) return;
    const iframe = iframeRef.current;

    if (iframe.contentWindow) {
      iframe.contentWindow!.addEventListener("error", onIframeError);
    }

    return () => {
      if (iframe.contentWindow) {
        iframe.contentWindow!.removeEventListener("error", onIframeError);
      }
    }
  }, [htmlBlock.html]);

  const onIframeError = (event: ErrorEvent) => {
    event.preventDefault();
    setHasError(true);
  };

  return !hasError ? (
    <iframe
      ref={iframeRef}
      srcDoc={htmlBlock.html}
      style={{
        border: "none",
        width: "100%",
      }}
    ></iframe>
  ) : (
    <Alert color="danger">There was an error loading the HTML content</Alert>
  );
};
tag5nh1u

tag5nh1u1#

我修改了您的代码以使用window.postMessage():

const RenderHtml = ({ htmlBlock }: { htmlBlock: HtmlBlock }) => {
const iframeRef = useRef<HTMLIFrameElement>(null);
const [hasError, setHasError] = useState<boolean>(false);

useEffect(() => {
if (!iframeRef.current) return;
const iframe = iframeRef.current;

if (iframe.contentWindow) {
  iframe.contentWindow!.postMessage("ready", "*");
  window.addEventListener("message", onIframeMessage);
}

return () => {
  if (iframe.contentWindow) {
    window.removeEventListener("message", onIframeMessage);
  }
 }
 }, [htmlBlock.html]);

const onIframeMessage = (event: MessageEvent) => {
if (event.data === "error") {
  setHasError(true);
}
};

return !hasError ? (
<iframe
  ref={iframeRef}
  srcDoc={htmlBlock.html}
  style={{
    border: "none",
    width: "100%",
  }}
  ></iframe>
 ) : (
<Alert color="danger">There was an error loading the HTML content</Alert>
 );
 };

在这段代码中,我们使用window.postMessage()在iframe准备就绪时向其发送消息。然后,我们将事件侦听器添加到窗口对象,以侦听来自iframe的消息。如果收到的消息是“error”,我们将hasError状态设置为true。看看能不能用

mpgws1up

mpgws1up2#

1.在useEffect钩子中移动错误处理逻辑,以确保在iframe准备就绪时正确设置它。
1.使用load事件而不是error事件来处理iframe内容中的潜在错误。
示例:

import React, { useEffect, useRef, useState } from "react";

const RenderHtml = ({ htmlBlock }: { htmlBlock: HtmlBlock }) => {
  const iframeRef = useRef<HTMLIFrameElement>(null);
  const [hasError, setHasError] = useState<boolean>(false);

  useEffect(() => {
    if (!iframeRef.current) return;

    const iframe = iframeRef.current;

    const handleLoad = () => {
      // Check if the iframe's contentDocument is accessible
      // and whether it contains any error messages
      if (iframe.contentDocument?.querySelector("body script[src^='chrome-error://']")) {
        setHasError(true);
      }
    };

    iframe.addEventListener("load", handleLoad);

    return () => {
      iframe.removeEventListener("load", handleLoad);
    };
  }, [htmlBlock.html]);

  return !hasError ? (
    <iframe
      ref={iframeRef}
      srcDoc={htmlBlock.html}
      style={{
        border: "none",
        width: "100%",
      }}
    ></iframe>
  ) : (
    <Alert color="danger">There was an error loading the HTML content</Alert>
  );
};

相关问题