Reputation: 35
I'm trying to loop this page for my chrome extension using javascript. What it does is it should keep running until it gets a response from "chrome.tabs.sendMessage" to stop running. The response function from "chrome.tabs.sendMessage" sends the correct boolean, but the rest of the code below does not work. When I run this code, console.log(cont) prints first, but console.log(response[0]) should be running first. I think it's an issue with async programming, but I am new to javascript and this kind of programming so I'm not sure how to fix it. Any advice or help is appreciated, thanks!
var temp = false;
function injectTheScript() {
var name = document.getElementById('name').value;
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.executeScript(tabs[0].id, {file: "utilities.js"}, function(){
chrome.tabs.sendMessage(tabs[0].id, name, function(response){
temp = response[0];
console.log(response[0]);
});
});
});
return temp;
}
function nextName() {
var cont = true;
while(cont){
cont = injectTheScript();
console.log(cont); //this gets printed first but should be printed second
}
}
document.getElementById('start').addEventListener('click', nextName);
This page is popup.js btw, it is the script behind popup.html, what the chrome extension shows when you click the icon.
Upvotes: 0
Views: 112
Reputation: 73846
Each JavaScript script's context is single-threaded so your synchronous while
loop will keep running forever in one event loop task, meaning none of the asynchronous callbacks of query(), executeScript(), and sendMessage() will ever run, and your extension will consume 100% CPU endlessly.
The solution is to make the loop asynchronous and let injectTheScript return the content script's response value via Promise
:
function injectTheScript() {
return new Promise(resolve => {
const name = document.getElementById('name').value;
chrome.tabs.query({active: true, currentWindow: true}, ([tab]) => {
chrome.tabs.executeScript(tab.id, {file: 'utilities.js'}, () => {
chrome.tabs.sendMessage(tab.id, name, resolve);
});
});
});
}
async function nextName() {
while (await injectTheScript()) {
console.log('yay');
}
}
The above code expects your onMessage listener in content script to return a boolean value via sendResponse:
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
// do something
// ..............
sendResponse(true); // or false
});
See tutorials on Promise
and asynchronous JavaScript for more info if needed.
Upvotes: 1