反应Chrome扩展程序和承诺

时间:2019-02-18 09:57:47

标签: reactjs google-chrome-extension

我正在用ReactJS编写一个Chrome扩展程序。

我正在遍历URL数组,并尝试获取这些页面的HTML内容。

this.state.advertData.map(function(e, i) {

    common.updateTabUrl(e.url).then((tab) => {

        common.requestHTML(tab).then((response) => {

            console.log(response.content);

        })

    });

})

common.js:

let requestHTML = function(tab) {

    return new Promise(function(resolve, reject) {

        chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
            chrome.tabs.sendMessage(tab.id, {'req': 'source-code'}, function (response) {

                resolve(response)

            })
        })

    })

}

let updateTabUrl = function(url) {

    return new Promise(function(resolve, reject) {

        let update = chrome.tabs.update({
            url: url
        }, function(tab) {
            chrome.tabs.onUpdated.addListener(function listener (tabId, info) {
                if (info.status === 'complete' && tabId === tab.id) {
                    chrome.tabs.onUpdated.removeListener(listener);
                    resolve(tab);
                }
            });


        })

    })
}

content_script.js

chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
    let response = '';
    if (request.req === 'source-code') {
        response = document.documentElement.innerHTML;
    }
    sendResponse({content: response});
});

我的问题是response.content似乎总是一样。更重要的是,更新的标签似乎只显示了数组中的最后一个URL。我认为我处理Promises的方式存在问题。

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

您的代码存在的问题是,在继续下一个URL之前,它不等待上一个URL加载,因此只有最后一个URL实际加载到了选项卡中。

我建议使用1)Mozilla's WebExtension polyfill,2)等待/异步语​​法,3)executeScript,该选项卡默认情况下会在选项卡完成时自动运行4)executeScript中的文字代码字符串,因此您不必既不需要单独的文件,也不需要在manifest.json中声明内容脚本。

async function getUrlSourceForArray({urls, tabId = null}) {
  const results = [];
  for (const url of urls) {
    await browser.tabs.update(tabId, {url});
    const [html] = await browser.tabs.executeScript(tabId, {
      code: 'document.documentElement.innerHTML',
    });
    results.push(html);
  }
  return results;
}

async函数内部调用:

const allHtmls = await getUrlSourceForArray({
  urls: this.state.advertData.map(d => d.url),
  tabId: null, // active tab
});

P.S。您还可以在后台的新窗口中一次打开所有URL,假设不会出现10个以上的URL,否则您将冒用尽用户RAM的风险。