如何使用chrome.tabs.insertCSS添加多个样式表?

时间:2014-01-21 16:10:24

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

我的chrome扩展程序中有一些代码连续多次调用chrome.tabs.insertCSS()(由于用户选择了可选样式,因此需要)。问题不在于代码不起作用,而是 工作,但我仍然在控制台中收到错误:Attempting to use a disconnected port object。在相关代码中,我使用chrome.tabs.connect(),所以我认为可以通过已经连接的端口发送该消息来解决这个问题,但我找不到办法来做到这一点。

我假设chrome.tabs.insertCSS()使用了下面的消息,因此有理由认为应该有一种方法让它使用已经在使用的端口。

我的问题是:是否可以告诉chrome.tabs.insertCSS方法使用已存在的开放端口而不是打开另一个端口?如果没有,将多个css / script文件动态加载到我的后台页面的选项卡中的最有效/最常用的方法是什么?

我的背景页:

function setUpListener() {
    chrome.runtime.onMessage.addListener(function (msg, sender, respond) {
        if (msg["injectCss"]) { 
            var port = chrome.tabs.connect(sender.tab.id, { name: "injection" });
            port.postMessage({ beginInject: msg.injectCss.files.length });
            injectCss(port, sender.tab.id, msg.injectCss.files, 0, function (port) {
                port.postMessage({ endInject: true });
                port.disconnect();
                respond();
            });
        }
        return true;
    });
}

function injectCss(port, tab, files, index, callback) {
    // TODO: try getting/compiling all .css files instead
    chrome.tabs.insertCSS(tab, { file: files[index++], runAt: "document_start" }, function () {
        if (index > files.length)
            return callback(port);
        return injectCss(port, tab, files, index, callback);
    });
}

编辑:我还考虑将所有必要的CSS编译到一个文件中,而不是多次调用insertCSS,但我似乎无法找到如何获取我的后台脚本中的那些文件的内容。

1 个答案:

答案 0 :(得分:1)

在没有看到与您使用消息传递API相关的所有代码的情况下,我无法具体说明您正在观察的“断开端口”错误。您可能在调用异步injectCss方法之前关闭端口(通过调用.disconnect()或卸载页面)。

您当前插入多个CSS文件的方式是可以的,但我会将index > files.length检查放在insertCss函数的顶部,以确保在未定义样式表时调用回调:

function injectCss(port, tab, files, index, callback) {
    if (index > files.length) {
        callback(port);
    } else {
        chrome.tabs.insertCSS(tab, { file: files[index] }, function () {
            injectCss(port, tab, files, index + 1, callback);
        });
    }
}

关于你的第二个问题(如何连接所有CSS文件),在插入之前:这可以通过多个XMLHttpRequest调用轻松实现(见下文)。我不明白你为什么要使用这个方法,多次调用insertCSS同样有效,并且优于下一个方法:如果一个文件是无效的CSS(例如因为缺少大括号) ),当您使用多个chrome.tabs.insertCSS来电时,其他文件不会受到影响。

function injectCss(port, tab, files, callback) {
    var allCss = new Array(files.length);
    var tasksToGo = files.length;
    if (tasksToGo === 0) {
        callback();
        return;
    }
    files.forEach(function(file, index) {
        var x = new XMLHttpRequest();
        x.open('GET', chrome.runtime.getURL(file));
        x.onload = function() {
            allCss[index] = x.responseText;
            if (--tasksToGo === 0) {
                chrome.tabs.insertCSS(tab.id, {
                    code: allCss.join('\n')
                }, callback);
            };
        };
        x.onerror = function() {
            // TODO: What if a file is missing?
        };
        x.send();
    });
}