Javascript chrome扩展中的异步调用问题

Javascript chrome扩展中的异步调用问题,javascript,asynchronous,google-chrome-extension,Javascript,Asynchronous,Google Chrome Extension,我有一个新chrome扩展的想法: 它应该为当前打开的网站创建一个链接QR码,显示在popup.html中,可以用智能手机轻松扫描。如果你在YouTube上观看视频,视频的当前时间也应嵌入二维码中,这样就可以直接在智能手机上的YouTube应用程序中继续观看视频 到目前为止还不错。但现在我有以下问题: 此扩展在所有网站上都可以正常工作。只有在Youtube上,onmessage侦听器的异步性和向contentScript发送消息(请求查看的Youtube视频的当前时间)似乎存在问题。 在调试控制

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

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

未选中的runtime.lastError:无法建立连接。接收端不存在

。。。在尝试执行background.js的第7行后获得此信息

错误处理响应:TypeError:无法读取未定义的属性“videoTime”

在铬-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;
}
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 */;
}

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;
});
background.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;
}
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 */;
}

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;
});
contentScript.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;
}
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 */;
}

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;
});
manifest.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"
    ]
}
我做到了

起初,我对通过额外的内容脚本管理youtube DOM访问的想法说再见。 所以我删除了contentScript.js,并将其从manifest.json中删除。 现在,我只是使用background.js文件中的方法访问DOM,并使用回调函数获得结果。非常简单-无需一直发送消息

我做到了

起初,我对通过额外的内容脚本管理youtube dom访问的想法说再见。 所以我删除了contentScript.js,并将其从manifest.json中删除。
现在,我只是使用background.js文件中的chrome.tabs.executeScript方法访问dom,并使用回调函数获得结果。非常简单-无需一直发送消息。

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