【问题标题】:Problems with asynchronous calls in chrome extensionchrome扩展中的异步调用问题
【发布时间】:2020-10-06 13:54:39
【问题描述】:

我有一个新的 chrome 扩展的想法: 它应该为当前打开的网站创建一个链接二维码,显示在 popup.html 中,可以用智能手机轻松扫描。如果您在 YouTube 上观看视频,该视频的当前时间也应该嵌入到二维码中,这样就可以直接在智能手机上的 YouTube 应用中继续观看视频。

到目前为止一切顺利。但现在我有以下问题: 此扩展程序在所有网站上都可以正常工作。只有在 Youtube 上,onmessage 侦听器的异步性和将消息发送到 contentScript(请求查看的 YouTube 视频的当前时间)似乎存在问题。 在调试控制台中,我收到以下错误:

未经检查的 runtime.lastError:无法建立连接。接收端不存在。

...在尝试执行 background.js 的第 7 行后得到这个

错误处理响应:TypeError: Cannot read property 'videoTime' of undefined

在 chrome-extension://...../background.js:8:70

...在尝试执行 background.js 的第 8 行后得到这个

popup.js

$(function() {
    chrome.runtime.sendMessage({text: 'sendURL'}, function(response) {
        $('#qr-code').attr('src', getQRCodeImgURL(response.url));
    });
});

function getQRCodeImgURL(url) {
    var qrCodeURL = new URL('http://api.qrserver.com/v1/create-qr-code/');
    qrCodeURL.searchParams.set('data', encodeURI(url));
    qrCodeURL.searchParams.set('size', '200x200');
    return qrCodeURL;
}

background.js

chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {

    if (message.text == 'sendURL') {
        chrome.tabs.query({active: true, /* lastFocusedWindow: true */}, function (tabs) {
            var currentURL = new URL(tabs[0].url);
            if (currentURL.href.indexOf('youtube.com/watch?v=') >= 0) { // if current website is youtube
                chrome.tabs.sendMessage(tabs[0].id, { text: 'sendVideoTime' }, function (response) {
                    const ytVideoTime = timeStringToSeconds(response.videoTime);

                    var ytURL = new URL('https://youtu.be/');
                    ytURL.pathname = '/' + currentURL.searchParams.get('v');
                    ytURL.searchParams.set('t', ytVideoTime);
                    currentURL = ytURL;
                    sendResponse({ url: currentURL.href });
                });
            } else {
                sendResponse({ url: currentURL.href });
            }
        });
    }
    return true;
});

function timeStringToSeconds(timeString) {
    var seconds = 0;
    var hms = timeString.split(':');
    if (hms.length == 3) {
        seconds = parseInt(hms[0])/* hours */ * 60 /* minutes per hour */ * 60 /* seconds per minute */;
        hms.shift(); /* remove first element, for accessing first element in next step (also if hms doesnt is in this hh:mm:ss format)  */
    }
    return seconds + (parseInt(hms[0]) * 60) /* seconds per minute */ + parseInt(hms[1]) /* seconds */;
}

contentScript.js


chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
    if (message.text == 'sendVideoTime') {
        const time = document.evaluate('//*[@id="movie_player"]/div[27]/div[2]/div[1]/div[1]/span[1]', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.textContent;
        sendResponse({videoTime: time});
    }
    return true;
});

ma​​nifest.json

{
    "manifest_version": 2,
    "name": "URL-QR-Code-Creator",
    "version": "1.0",
    "description": "This extension creates a linking QR code for the currently open website, which can be easily scanned with the smartphone. If you watch a video on the YouTube website, the current time of the video is also embedded in the QR code, which makes it possible to continue watching the video directly in the YouTube app on the smartphone.",
    "icons": {
        "16": "images/qr-code-16px.png",
        "32": "images/qr-code-32px.png",
        "48": "images/qr-code-48px.png",
        "64": "images/qr-code-64px.png",
        "128": "images/qr-code-128px.png"
    },
    "browser_action": {
        "default_icon": {
            "16": "images/qr-code-16px.png",
            "32": "images/qr-code-32px.png",
            "48": "images/qr-code-48px.png",
            "64": "images/qr-code-64px.png",
            "128": "images/qr-code-128px.png"
        },
        "default_title": "show QR-Code",
        "default_popup": "popup.html"
    },
    "background": {
        "scripts": [
            "background.js"
        ],
        "persistant": false
    },
    "content_scripts": [
        {
            "matches": ["*://www.youtube.com/watch?v=*"],
            "js": ["contentScript.js"]
        }
    ],
    "permissions": [
        "activeTab",
        "tabs"
    ]
}

【问题讨论】:

  • “接收端不存在”告诉您在发送消息的确切时刻标签中没有运行内容脚本。向我们展示您如何声明/注入 contentScript.js
  • 将 manifest.json 添加到我上面的帖子中。 :)
  • Youtube 是一个 SPA 网站,所以当您先打开它的主页然后导航到观看页面时,那里不会运行任何内容脚本。你需要匹配"*://www.youtube.com/*"
  • 将匹配模式更改为“[star]://www.youtube.com/[star]”,但同时仍然出现相同的错误。
  • 好吧,您需要重新加载扩展程序和选项卡。此外,如果 youtube 仍在加载,您的内容脚本将不会运行,因此您可能需要指定 run_at。

标签: javascript asynchronous google-chrome-extension


【解决方案1】:

我做到了!

起初,我放弃了通过额外的内容脚本来规范对 youtube DOM 的访问的想法。 所以我删除了 contentScript.js 并将其从 manifest.json 中删除。 现在我简单地使用 background.js 文件中的chrome.tabs.executeScript 方法访问 DOM,并使用回调函数得到结果。很简单 - 无需一直发送消息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-27
    • 2018-11-24
    • 1970-01-01
    • 2019-11-01
    相关资源
    最近更新 更多