【问题标题】:Violation 'setTimeout' handler took <N>ms违反“setTimeout”处理程序花费了 <N> 毫秒
【发布时间】:2021-10-06 23:39:40
【问题描述】:

我在我的页面中收到此控制台警告 -

[Violation] 'setTimeout' handler took <N>ms

我已经检查了这个问题,我得到了很多答案,但无法解决这个违规警告。

这是我的 useEffect 代码 -

useEffect(() => {
        const timer = setTimeout(() => {
            const diffArr = getDiffArray(
                props.startupConfigData,
                props.runningConfigData
            );
            if (diffArr.length > 0) {
                setDiffArr(diffArr);
                setIsLoading(false);
            }
        }, 200);
        return () => clearTimeout(timer);
    });

这是我的完整文件 -

import React, { useState, useEffect } from "react";
import { diffLines, formatLines } from "./unidiff";
import { parseDiff, Diff, Hunk } from "react-diff-view";
import { getComplianceIcon, getFormattedDate } from "../common";
import "./diff.less";
import "react-diff-view/style/index.css";

/**
 * This constant is used for chunking.
 * A value of 3000 takes ~ 15 secs to show the diff for real data
 * A value of 2000 takes ~ 12 secs to show the diff for real data
 */
const THRESHOLD = 2000; //changing this is reflecting in response time, need to check

const DiffViewer = props => {
    const { startUpFile, runningFile, showLoader, compareWith } = props;
    const [diffArr, setDiffArr] = useState([]);
    const [isLoading, setIsLoading] = useState(true);

    useEffect(() => {
        const timer = setTimeout(() => {
            const diffArr = getDiffArray(
                props.startupConfigData,
                props.runningConfigData
            );
            if (diffArr.length > 0) {
                setDiffArr(diffArr);
                setIsLoading(false);
            }
        }, 200);
        return () => clearTimeout(timer);
    });

    /**
     * Returns an array of differences in the unidiff format
     *
     * @param {string} oldLongText - the old string to compare
     * @param {string} newLongText - the new string to compare
     * @returns {Array} - the array having the diff objects
     */
    const getDiffArray = (oldLongText = "", newLongText = "") => {
        if (oldLongText !== newLongText) {
            const oldTextChunks = getChunkedLinesOfText(oldLongText, THRESHOLD);
            const newTextChunks = getChunkedLinesOfText(newLongText, THRESHOLD);
            const chunkMaxLen = Math.max(oldTextChunks.length, newTextChunks.length);
            const zipChunks = (_, i) => [
                oldTextChunks[i] || "",
                newTextChunks[i] || ""
            ];
            const unmodDiffContext = chunkMaxLen > 1 ? 3 : 500;
            return Array.from({ length: chunkMaxLen }, zipChunks).reduce(
                (res, [oldText, newText], idx) => {
                    const diffText = computeDiff(oldText, newText, unmodDiffContext);
                    if (diffText) {
                        const maxLenOfText =
                            idx * THRESHOLD +
                            Math.max(oldText.split("\n").length, newText.split("\n").length);
                        res.push({ diffText, start: idx * THRESHOLD, end: maxLenOfText });
                    }
                    return res;
                },
                []
            );
        }
        return [];
    };

    /**
     * Splits input text into chunks of specified size
     *
     * @param {string} text - takes the input text and splits it into chunks
     * @param {number} threshold - takes a threshold which is the chunk size
     * @returns {Array} - returns an array of strings as specified by the chunk size
     */
    const getChunkedLinesOfText = (text = "", threshold = 3000) => {
        const totalLines = (typeof text === "string" && text.split("\n")) || [];
        if (threshold > 0 && totalLines.length > threshold) {
            const chunks = Math.ceil(totalLines.length / threshold);
            const chunkArray = (_, idx) =>
                totalLines
                    .slice(idx * threshold, idx * threshold + threshold)
                    .join("\n");
            return Array.from({ length: chunks }, chunkArray);
        }
        return [text];
    };

    const computeDiff = (oldText = "", newText = "", unmodDiffContext = 3) => {
        return formatLines(diffLines(oldText, newText), {
            context: unmodDiffContext
        });
    };

    const renderFile = (
        { oldRevision, newRevision, type, hunks },
        start,
        end,
        isFirstDiff
    ) => {
        const separator = `${i18n.diff_showing_lines} ${start} - ${end}`;
        return (
            <div
                className="diff-div margin-left-5px"
                key={oldRevision + `${separator}` - +newRevision}
            >
                {!isFirstDiff && <div className="diff-separator">{separator}</div>}
                <Diff
                    key={oldRevision + `${separator}` - +newRevision}
                    viewType="split"
                    diffType={type}
                    hunks={hunks}
                >
                    {hunks => hunks.map(hunk => <Hunk key={hunk.content} hunk={hunk} />)}
                </Diff>
            </div>
        );
    };

    /**
     * Get text based on selection - startup/running
     */
    const getStartupText = () => {
        if (compareWith == undefined || compareWith === "startup") {
            return i18n.label_startup_configuration;
        } else {
            return i18n.label_running_configuration;
        }
    };

    const statusDisplayDetails = getComplianceIcon("COMPLIANT", true);
    const DiffData_Loading = () => {
        let loderLabel;
        let loderLabelExtraTime = i18n.take_while_text;
        if (props.runningFile)
            loderLabel =
                props.runningFile.totalNoOfLines < 5000
                    ? "Loading..."
                    : loderLabelExtraTime;
        return (
            <div className="loading-icon">
                <DnxLoader color="#026E97" size="54" label={loderLabel} />
            </div>
        );
    };

    /**
     * Function returns the DnxBanner information text for diff Position Mismatch
     */
    const _diffPositionMismatchInfoText = () => {
        const informationConfig = {
            message: i18n.diff_postion_mismatch_info,
            type: "information"
        };
        return (
            <div className="margin-5px">
                <DnxBanner name="banner-loading" config={informationConfig}></DnxBanner>
            </div>
        );
    };

    /**
     * return function
     */
    return (
        <div className="">
            <div>
                {startUpFile && runningFile ? (
                    <div>
                        {showLoader ? (
                            DiffData_Loading()
                        ) : (
                            <div>
                                <div className="flex margin-left-5px">
                                    <div className="startup-text">
                                        {getStartupText()} ({startUpFile.totalNoOfLines}{" "}
                                        {i18n.label_lines}) -{" "}
                                        {getFormattedDate(startUpFile.createdTime)}
                                    </div>
                                    <div className="running-text">
                                        {i18n.label_running_configuration} (
                                        {runningFile.totalNoOfLines} {i18n.label_lines}) -{" "}
                                        {getFormattedDate(runningFile.createdTime)}
                                    </div>
                                </div>
                                {diffArr &&
                                props.startupConfigData !== props.runningConfigData ? (
                                    <div>
                                        {isLoading && DiffData_Loading()}
                                        {!isLoading && (
                                            <div>
                                                {diffArr.map(({ diffText, start, end }, idx) =>
                                                    parseDiff(diffText, { nearbySequences: "zip" }).map(
                                                        file => renderFile(file, start, end, idx === 0)
                                                    )
                                                )}
                                            </div>
                                        )}
                                    </div>
                                ) : (
                                    <div className="div-margin-diff">
                                        {statusDisplayDetails}
                                        <span>
                                            {compareWith === "running"
                                                ? i18n.label_running_config_compliant
                                                : i18n.label_running_startup_config_compliant}
                                        </span>
                                    </div>
                                )}
                            </div>
                        )}
                    </div>
                ) : (
                    <div className="div-margin-diff">
                        <span>{i18n.label_running_config_not_available}</span>
                    </div>
                )}
            </div>
            {_diffPositionMismatchInfoText()}
        </div>
    );
};

export default DiffViewer;

请指导我应该改变什么。

【问题讨论】:

  • 您有幸找到解决方案吗?我遇到了同样的问题。

标签: javascript reactjs


【解决方案1】:

是浏览器试图告诉您处理函数(在主线程上执行以响应事件发生的一段 javascript 代码)花费的时间比应有的时间长,并且可能对事件循环造成潜在的阻塞。

避免阻塞事件循环的想法是编写高性能 JS 应用程序的核心。

警告本身现在不会损害您的应用程序,但如果您不关心您在“处理程序”函数中放入的同步工作量,它可能会导致您的脚本阻塞。

【讨论】:

    猜你喜欢
    • 2022-06-17
    • 2017-09-02
    • 2017-07-02
    • 2021-05-06
    • 2017-10-06
    • 1970-01-01
    • 1970-01-01
    • 2015-08-06
    相关资源
    最近更新 更多