I wrote a chrome extension, popup js will send a message to background and background will redirect the message to content script, after some network request, the result should be returned to the background and then popup js.
Below are some simplified pieces of my code.
popup js
$('.porintButton').click(function() {
switch (this.id) {
case 'learningPointButton':
chrome.runtime.sendMessage({ action: 'learning' }, callback);
processResult();
break;
}
return true;
});
backgound js
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, request, response => {
if (chrome.runtime.lastError) {
// If I click learningPointButton, the line will excute, and log 'ERROR: {message: "Could not establish connection. Receiving end does not exist."}'
console.log('ERROR: ', chrome.runtime.lastError);
} else {
console.log('The Content Script got the following Message: ' + JSON.stringify(response));
sendResponse(response);
}
});
});
return true;
});
content script
chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
console.info('contentscript', request, sender);
switch (request.action) {
case 'learning':
// this simulate network async request, will not work,
setTimeout(() => {
sendResponse({ action: request.action, result: 'ok' });
}, 0);
// this works
// sendResponse({ action: request.action, result: 'ok' });
break;
}
// I have read https://developer.chrome.com/extensions/messaging#simple and return true here
return true;
});
If I change the message tunnel to the Long-lived connections, it will work, why?
@wOxxO Thanks, you are right.
I rewrite the code using Promise style, and it works now.
my rewritten code like this.
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.info('contentscript', request, sender);
switch (request.action) {
case 'learning':
Promise.all([doLearning(), doLearning(), doLearning()])
.then(unusedData => {
return getScore();
})
.then(scores => {
console.info(scores);
sendResponse({ action: request.action, result: 'ok', scores: scores });
})
.catch(e => {
console.error(e);
sendResponse({ action: request.action, result: 'error', message: e });
});
break;
case 'score':
getScore().then(scores => {
console.info(scores);
sendResponse({ action: request.action, result: 'ok', scores: scores });
}).catch(e => {
console.error(e);
sendResponse({ action: request.action, result: 'error', message: e });
});
break;
}
return true;
});
And I can send message from popup to contentscript directly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With