问题
In my extension i have in background.js
an onUpdated
listener, which pulls some data with XHR
and XPath
into badgeText
.
But, if i activated an old tab without to do anything in it, just click on its tab in the tab bar, onUpdated
isn't fired and i have in the badge data from the previously opened tab.
The similar happens with old tabs, which were discarded
. If i click on their tabs in the tab bar (again, without to do anything) onUpdated
isn't fired.
It seems to be, that onUpdated
doesn't covers an activation of the tab.
How can i use simultanously onUpdated
and onActivated
to cover events i described? Or is there any other approach to catch an event of the tab, where i just click on the tab in the tab bar?
I want to bind my XHR
and setBadgeText
action to both of onUpdated
and onActivated
, so simple clicking on the tab in the tab bar becomes a trigger too. In other case i should force users of my extension to manually refresh pages to get new data.
PS: this is background.js
var currentDomain = "";
var currentHost = "";
var currentFullpath = "";
var currentUrl = "";
var currentFolder = "";
var badgeText = "";
chrome.tabs.onUpdated.addListener(function(tabid, changeInfo, tab){
chrome.tabs.query({'active' : true, 'currentWindow': true}, function(tabs){
if( ! (tabs.length == 0)){
let newUrl = new URL(tabs[0].url);
currentHost = newUrl.host;
currentUrl = tabs[0].url;
currentFullpath = currentUrl.substring(0, currentUrl.lastIndexOf("/"));
currentFolder = currentUrl.split("/");
parsed = psl.parse(currentHost);
currentDomain = parsed.domain;
chrome.storage.sync.get('savedApi', ({savedApi}) => {
console.log("savedApi: "+savedApi);
if(savedApi == null)
savedApi = 'de';
if(currentDomain == null)
return false;
if(currentUrl == null)
return false;
var xhr = new XMLHttpRequest();
var protocol = "https://";
var middle = ".myservice.com/seo/__loadModule/domain/"
var end = "/mobile/1/_action/_data_visindex_normal/";
console.log("xhr: "+xhr);
xhr.open("GET", protocol+savedApi+middle+currentDomain+end, true);
xhr.responseType='document';
xhr.onreadystatechange = function() {
if (this.readyState == 4) {
function getElementByXpath(path) {
return xhr.response.evaluate(path, xhr.response, null, XPathResult.STRING_TYPE, null).stringValue;
}
badgeText = getElementByXpath("normalize-space(//div[@class='data']/span[@class='value']/text())");
console.log("newUrl: "+newUrl);
console.log("currentHost: "+currentHost);
console.log("currentUrl: "+currentUrl);
console.log("currentFullpath: "+currentFullpath);
console.log("currentFolder: "+currentFolder);
console.log("currentDomain: "+currentDomain);
chrome.browserAction.setTitle({title: "Mobile visibility of "+currentDomain+" is "+ String(badgeText)});
chrome.browserAction.setBadgeText({text: String(badgeText)});
chrome.browserAction.setBadgeBackgroundColor({ color: '#1d2554' });
}
}
xhr.send();
})
}
})
})
回答1:
Use both listeners and one common function that does the job. To avoid double invocation set tabId's "processing" state in a global object, clear it when done.
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (changeInfo.url) run(tab);
});
chrome.tabs.onActivated.addListener(info => {
chrome.tabs.get(info.tabId, run);
});
const processingTabId = {};
function run(tab) {
if (processingTabId[tab.id]) return;
processingTabId[tab.id] = true;
let newUrl = new URL(tab.url);
currentHost = newUrl.host;
currentUrl = tab.url;
doSomeAsyncStuff(() => {
//................................
// when all done:
delete processingTabId[tab.id];
});
}
Note there's no need for chrome.tabs.query because onUpdated already gives you the tab
object. Also not only active tab get updates, the inactive ones do too. And not just URLs are reported: also favicon, title, muted state, and many other things.
来源:https://stackoverflow.com/questions/60545285/how-to-use-onupdated-and-onactivated-simultanously