我正在用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);
})
});
})
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);
}
});
})
})
}
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的方式存在问题。
感谢您的帮助。
答案 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的风险。