javascript - 为什么后台js处理时扩展程序的弹出窗口会被阻止?

标签 javascript google-chrome-extension

我想构建一个 chrome 扩展来抓取(部分)网站。 从弹出窗口中,我想从后台调用异步方法,在其中执行一些阻止请求。在此调用之后,我想通过请求有关 setInterval 的一些信息来在弹出窗口中显示状态...启动进程后,弹出窗口将被锁定,直到后台进程结束。我尝试了很多解决方案,例如后台收到消息后返回 true、在后台启动异步进程,但我没有解决方案...... 这是我的代码:

list

{
  "manifest_version": 2,
  "name": "...",
  "description": "...",
  "version": "1.0",
  "browser_action": {
   "default_icon": "logo_76.png",
   "default_popup": "main.htm"
  },
  "background": {
    "scripts": [
                "lib/regex_utils.js",
                "lib/uri.js",
                "lib/uri_utils.js",
                "lib/bloomfilter.js",
                "background.js"
                ],
    "persistent": true
  },
  "content_scripts":[{
        "matches": ["*://*/*"],
        "js":      ["content.js"]
    }],
  "permissions": [
    "activeTab",
    "http://*/*",
    "https://*/*"
    ]
}

弹出窗口

var t = null;
var port = null;

function showStatus(response){
    // document.getElementById('start').innerHTML = 'parsed ' + response['parsed']
    console.log(response);
}

function checkStatus(){
    console.log('check')
    if(port){
        var data = {};
        data['command'] = 'status';
        port.postMessage(data); 
    }
}

clearInterval(t); t = setInterval(checkStatus, 2000);

document.addEventListener('DOMContentLoaded', function() {
    var checkPageButton = document.getElementById('start'); 
    checkPageButton.addEventListener('click', function() {
        chrome.tabs.getSelected(null, function(tab) {
            port = chrome.extension.connect({name: "communication"});
            var data = {}
            data['command'] = 'start_crawl'
            data['url'] = tab['url']
            port.postMessage(data);
            port.onMessage.addListener(function(msg) {
                if(msg['parsed'] != undefined){
                    showStatus(msg);                    
                }
            });
        });
  }, false);
}, false);

背景

function getLinksFromUrl(url){
    var xhr = new XMLHttpRequest();
    var data = null;
    var base = null;
    xhr.open("GET", url, false);

    function handleStateChange() {
      if (xhr.readyState == 4 && xhr.status==200) {
        data = xhr.responseText;
      }
    }

    xhr.onreadystatechange = handleStateChange;
    try {
        xhr.send();
    }catch(err){
        console.log('request exception');
    }

    if(data){
        linkRegex = new RegExp('a[^>]+?href=["\']{0,1}([^"\'\\s>]+)','igm');
        baseRegex = new RegExp('base[^>]+?href=["\']{0,1}([^"\'\\s>]+)','igm');
        var matches = linkRegex.execAll(data);  

        var base = baseRegex.exec(data);
        if (base && base[1] != undefined){
            base = base[1]
        }

        var rawLinks = matches.map(function(e){
            return e[1];
        });

        // Check to be on the same
        var finalLinks = relative2absolute(rawLinks, url, base).filter(function(e){
            var uri = new URI(e);
            if(ROOT_DOMAIN == uri.domain()){
                return true;
            }
            return false;
        });

        return finalLinks;
    }
    return [];
}

var TO_CRAWL = [];
var ALL_UNIQUE_URLS = []
var PASRSED_URLS = new BloomFilter();
var PAGE_LIMIT = 150;
var PARSED = 0;
var ROOT_DOMAIN = '';

function async(fn, callback) {
    setTimeout(function() {
        fn();
        callback();
    }, 0);
}

function getStatus(){
    var data = {}
    data['parsed'] = PARSED
    data['unique'] = ALL_UNIQUE_URLS.length
    data['queue'] = TO_CRAWL.length
    return data;
}

function crawl(initialUrl){
    var uri = new URI(initialUrl)
    ROOT_DOMAIN = uri.domain()
    TO_CRAWL = []
    ALL_UNIQUE_URLS = []
    PASRSED_URLS = new BloomFilter()
    PARSED = 0
    TO_CRAWL = getLinksFromUrl(initialUrl);
    while(ALL_UNIQUE_URLS.length < PAGE_LIMIT && TO_CRAWL.length > 0){
        url = TO_CRAWL.pop();
        var links = getLinksFromUrl(url)
        // TODO Add extra check for 404 and other error codes

        // Mark current URL as crawled
        PARSED++;
        PASRSED_URLS.add(url);
        ALL_UNIQUE_URLS.push(url);

        // Add new URls in queue
        links = links.filter(function(e){
            // TODO check domain here
            if(!PASRSED_URLS.check(e)){
                return true;
            }
            return false;
        });
        TO_CRAWL.push.apply(TO_CRAWL, links);
    }
}


chrome.extension.onConnect.addListener(function(port) {
  port.onMessage.addListener(function(data) {
    if (data['command'] != undefined && data['command'] == 'start_crawl'){
            async(
                    function(){
                        crawl(data['url']);
                    },
                    function(){
                        console.log(ALL_UNIQUE_URLS);
                    }
                );
            // SECOND METHOD TO SEND DATA AT POPUP
            var interval = setInterval(function(){
                port.postMessage(JSON.stringify(getStatus()));
            }, 1000);

        console.log('started')
        port.postMessage('crawling started');   
    }
    // FIRST METHOD TO SEND DATA AT POPUP
    if (data['command'] != undefined && data['command'] == 'status'){
        port.postMessage(JSON.stringify(getStatus()));
    }        
  });
});

最佳答案

正如 Chrome 46 上的控制台警告消息所示:

Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check http://xhr.spec.whatwg.org/.

这意味着您遇到的 UI 锁定正是所提到的“有害影响”。将来,在 Web Worker 之外使用时,同步 XHR 甚至无法工作:

Synchronous XMLHttpRequest outside of workers is in the process of being removed from the web platform as it has detrimental effects to the end user's experience. (This is a long process that takes many years.) Developers must not pass false for the async argument when the JavaScript global environment is a document environment. User agents are strongly encouraged to warn about such usage in developer tools and may experiment with throwing an InvalidAccessError exception when it occurs. (source)

解决方案是使用异步 XHR 或将其放入 Web Worker 中。

关于javascript - 为什么后台js处理时扩展程序的弹出窗口会被阻止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32221001/

相关文章:

javascript - Chrome 扩展程序是否可以获取用户的完整浏览历史记录?

javascript - 相对于浏览器窗口的宽度出现的动态下拉菜单

javascript - 使用 HTML 和 Javascript 函数调用 PHP 变量

javascript - 加载页面上的所有图像并等待完成

javascript - 创建多行文件并使用 Chrome.downloads.download 下载

google-chrome-extension - Chrome 中的自定义协议(protocol)处理程序

javascript - 来自 Chrome 扩展的跨源 XMLHttpRequest 返回状态 0

javascript - 具有较低 zIndex 的图层上的 Google map 点击事件

javascript - 如何多次追加 HTML 元素

javascript - chrome本地存储异步传递数据以正确回调