【问题标题】:chrome extension - best method of reducing load time while using content scriptschrome 扩展 - 使用内容脚本时减少加载时间的最佳方法
【发布时间】:2015-09-06 12:47:04
【问题描述】:

我正在构建一个 chrome 扩展,它应该查看包含超过 12,000 个值的数组并将其与网页 p 标签进行比较,如果数组中的值在 p 标签内,它应该突出显示文本和悬停时应该显示一些信息。所以,我想使用内容脚本很容易,但使用"run_at": "document_end" 会使网页加载速度慢 3 倍,我的扩展程序加载时间增加了近 10 秒。显然不理想。

这是我的内容脚本代码:

jQuery(document).ready(function($) {

var $all_p = $("p");

$.each(arrayObj, function(key, value) {
      $all_p.highlight(key, {caseSensitive: true, className: 'highlight-882312', wordsOnly:true });
});

$('.highlight-882312').each(function() {    

    var currentKey = $(this).text();
    console.log(currentKey);

        //Create tooltip on hover.
        Tipped.create(this, "<iframe id='cardiFrame' src='https://mywebsite.com/word?q="+footballers[currentKey]+"'></iframe>", {
            skin: "white",
            hook: 'rightmiddle',
            maxWidth: 306,
            maxHeight: 365,
            background: '#eee',
        }); 

});
});

无论如何,这对我来说太慢了,但我仍然想构建扩展,所以我想我可以将所有 p 标签的数组发送到我的背景/弹出窗口,以便在背景/弹出窗口中它会循环查找关键字,然后在弹出窗口中显示匹配的关键字,并将消息发送回关键字匹配的内容脚本,以便突出显示它们。这会减少加载时间吗?由于额外的 10 秒加载时间根本不理想,这对我的问题来说是一个很好的解决方法吗?

我真的很感激任何建议。

编辑:arrayObj:

var arrayObj = {

"word1": 'word_word1',
"word2": 'word_word2',
"word3": 'word_word3',

// extra 12K lines...
}

Manifest.json:

我的manifest很典型,但是内容脚本信息是:

 "content_scripts": [
    {
      "matches": ["http://*/*", "https://*/*"],
      "css": ["styles.css", "tipped.css"],
      "js": ["jquery.min.js", "jquery-highlight1.js", "spinners.min.js", "tipped.js", "word.js", "script.js"],
      "run_at": "document_end"
    }
  ],

【问题讨论】:

  • 欢迎来到 SO。不幸的是,“建议”在这个网站上做得不好。另一方面,需要 10 秒的扩展是我们可以提供帮助的。但我无法理解你想要做什么。你能发布你的清单吗?还有arrayObj?我的猜测是您正在创建 12,000 个 iframe,这会减慢速度。
  • @Teepeemm 进行了编辑。
  • .highlight 是做什么的?您不能只在一个循环中进行 12000 次 DOM 访问,一次获取 Ps,将文本放入哈希中,然后(使用 trie)将您的文本与 Ps 匹配,然后再次找到 Ps(您有来自哈希)并为它们着色。这将读取 Ps 一次,然后对每个 P 进行 trie 搜索。比每个 P 标签上的 12000 个 dom 操作快得多。

标签: javascript jquery google-chrome google-chrome-extension


【解决方案1】:

更新 http://jsfiddle.net/r4bnxemL/3/

这种新方法不太复杂,它不会将每个单词合并到一个大的正则表达式中。相反,它只是使用 setTimeout 技巧使用 asycn 循环方法。

var words = ['dolor', 'sit', 'odio'];

var ele = document.getElementById('text'),
    html = ele.innerHTML;


asycnIterator(words,
    function (word) {
        var reg = new RegExp('\\b' + word + '\\b', 'ig');
        html = html.replace(reg, '<span class="marked">' + word + '</span>');
    }, function () {
        ele.innerHTML = html;
});

function asycnIterator(arr, func, cb) {
    var i = 0;

    nextCall();

    function nextCall() {
        func(arr[i++]);
        if (i >= arr.length) {
            if (cb) cb();
            return;
        }
        setTimeout(nextCall, 1);
    }
}

首先,您可以做两件事,首先将循环分成小块,这可能会使整个过程在更多时间完成,但它不会阻塞其他所有内容,Javascript 单线程因此使用事件循环。

例如,您可以使用 setTimeout 来完成。 (注意需要使用回调模式,因为它会立即返回,下一行的执行不会等待循环完成)

var arr = [1,2,3....100000];
var i = 0 ;
nonBlockingAsycnLoop(); //will prints all values in console without blocking

function nonBlockingAsycnLoop() {
   console.log(arr[i++]);
   setTimeout(nonBlockingAsycnLoop,0);
}

您可以做的第二件事是加快查找速度。就此而言,您使用的本地方法越多越好。这只是我的方法

  1. 将所有数组元素连接成一个字符串
  2. 然后将它们用作正则表达式进行搜索
  3. 存储索引

以下函数会执行此操作并使用所有出现的列表调用 cb。

function returnOccurences(str, arr, cb) {
    var ele = null,
        index = 0,
        occurences = [],
        regexp = '\\b' + arr.join('\\b|\\b') + '\\b';

    getNextWord();
    function getNextWord() {
        ele = str.substr(index).match(new RegExp( regexp , 'i'));
        if (!ele) {
            cb(occurences);
            return;
        }
        occurences.push({i: ele.index, len: ele[0].length, word: ele[0]});
        index = ele[0].length + ele.index;
        setTimeout(getNextWord,0); //makes it non blocking
    }
}

字符串匹配函数文档MDN LINK 如果没有为正则表达式调用参数g,则它返回具有不可枚举属性的数组,这些属性是找到的单词的索引和包含原始文本的输入。

我们可以在第一次匹配后使用索引进一步解析前面的字符串。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-01
    • 2011-11-25
    • 1970-01-01
    • 2012-05-25
    • 2016-04-22
    • 2011-07-03
    • 2022-12-15
    • 1970-01-01
    相关资源
    最近更新 更多