Chrome扩展程序:从标签中提取关键字不起作用

Chrome Extension: extracting keywords from tab not working

本文关键字:提取 关键字 不起作用 标签 扩展 程序 Chrome      更新时间:2023-09-26

我正在编写一个Chrome扩展程序,以类似于Delicious的方式存储链接。作为扩展的一部分,我想保存我正在存储的链接的关键字。为了获得此关键字,我使用以下函数:

EXT.get_keywords = function (tab) {
var keywords = [];
    if(tab) {
        chrome.tabs.executeScript(tab.id, {file:"js/keywords.js"},
            (function(keywords) {
                return function (res) {
                    var kw_str = res && res[0];
                    if (kw_str) {
                        keywords.push.apply(keywords, kw_str.split(","));
                    }
                }
            })(keywords));
    }
    console.log(keywords);
    return keywords;
}    

"js/关键字.js"文件的内容如下:

var metas = document.getElementsByTagName('meta'),
    i = 0,
    result = "";
for (i = 0; i < metas.length; i++) {
    if (metas[i].getAttribute("name") === "keywords") {
        result = metas[i].getAttribute("content");
        break;
    }
}
result;

"js/关键字.js"脚本运行良好,回调函数从关键字标签中获取内容字符串(如果存在),但是在执行回调后,关键字变量始终[]。知道吗?

PS:这很奇怪,因为如果我在console.log(keywords)行执行带有断点的脚本,它可以工作,但如果断点不存在,它就不会:S。

这是

由于chrome.tabs.executeScript()的异步性质。您无法从get_keywords函数返回关键字 - 实际上您可以返回一个空的keywords数组,但在函数退出之前不会填充它。
(大多数 chrome.* API 都是异步的,因此您必须调整整个扩展"样式"以符合此要求。

那么,会发生什么呢?

这是执行顺序:

  1. 空的keywords数组被初始化(var keywords = [];)。
  2. executeScript被称为在后台启动一些令人讨厌的东西。
  3. 调用(function(keywords) {...})(keywords),返回并注册一个回调(绑定到仍然为空的 keywords 数组)。每次注入和执行结束后,将调用回调。
  4. executeScript返回(请注意,尚未执行回调 - 不合时宜地仍在后台执行操作,即注入和执行 JS)。
  5. console.log(keywords);记录(仍然为空的)keywords数组。
  6. 返回仍然为空的keywords数组 ( return keywords; )。
  7. 异步注入/执行结束,调用回调,填充keywords数组。

如果激活断点,则在到达步骤 5 之前有时间完成注入/执行,因此在返回 keywords 数组之前填充它。


演示这一点的示例扩展:

后台.js,keywords数组被记录两次:一次在getKeywords()返回之前,一次在回调中填充之后。如您所见,在返回空数组getKeywords()执行回调日志记录。

内容.js:

var metas = document.getElementsByTagName("meta");
var result = "";
for (var i = 0; i < metas.length; i++) {
    var meta = metas[i];
    if (meta.name && (meta.name.toLowerCase() === "keywords")) {
        result = meta.content;
        break;
    }
}
result;

背景.js:

function getKeywords(tab) {
    var keywords = [];
    chrome.tabs.executeScript(
            tab.id,
            { file: "/fg/content.js" },
            (function(keywords) {
                return function(resultArr) {
                    if (!chrome.runtime.lastError && resultArr[0]) {
                        keywords.push.apply(keywords, resultArr[0].split(","));
                    }
                    console.log("After: ", keywords);
                }
            })(keywords));
    console.log("Before: ", keywords);
}
chrome.browserAction.onClicked.addListener(getKeywords);

manifest.json:

{
    "manifest_version": 2,
    "name":    "Test Extension",
    "version": "0.0",
    "background": {
        "persistent": false,
        "scripts": ["./bg/background.js"]
    },
    "browser_action": {
        "default_title": "Test Extension"
    },
    "permissions": ["activeTab"]
}