问题
The content script of my chrome extension has two event listener functions. The two functions sends different variable as message. So if the background script wants to distinguish between these events / variables how do I do this?
Can I have multiple functions in background scripts to listen to particular type of events only? If yes, how can I achieve this.
Currently I am sending an id 1 and 2 (along with the message to background script) from each of the function and using if-else to distinguish which message is from which function. I don't think this is a very elegant solution.
Content Script:
document.getElementById("myBTN").addEventListener('click', wordSelected) {
// code
chrome.runtime.sendMessage(var1, (response) => { // id = 1
// code
});
}
window.addEventListener('change', (e)=> {
// code
chrome.runtime.sendMessage(var2, (response) => { // id = 2
// code
});
}
Background Script:
chrome.runtime.onMessage.addListener(receiver);
function receiver(request, sender, sendResponse) {
if (request.id == 1) {
// code
}
else if (request.id == 2) {
// code
}
回答1:
Sending an id
or cmd
or action
or method
property along with the actual value is the standard solution, there is no better one conceptually. You can use id: 'clicked'
and id: 'changed'
instead of numeric indexes.
As far as the cosmetic "solutions" go, you can use Proxy
API to wrap chrome.runtime.sendMessage, for example as HQ ("headquarters") object:
async function queryHQ() {
if (await HQ.test(1, 2, 3) === 123) {
console.log('ok!');
} else {
console.log(await HQ.download());
}
}
For this to work, first let's define HQ
in the content script:
const HQ = new Proxy({}, {
get: (_, cmd) =>
(...args) =>
new Promise((resolve, reject) =>
chrome.runtime.sendMessage({cmd, args}, r =>
!r || 'error' in r ? reject(r && r.error) : resolve(r.data)))
});
In the background script define a command map:
const handlers = {
test(a, b, c) {
console.log(a, b, c);
return 123;
},
async download() {
return (await fetch(this.url)).text();
},
};
...and a listener:
const wrapError = error => ({error: error && error.message || `${error}`});
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
const {cmd, args} = msg;
const fn = handlers[cmd];
try {
const res = fn.apply(sender, args);
if (typeof res?.then === 'function') {
res.then(data => ({data}), wrapError)
.then(sendResponse);
return true;
} else if (res !== undefined) {
sendResponse({data: res});
}
} catch (error) {
sendResponse(wrapError);
}
});
There are libraries for chrome extensions that implement a similar approach.
来源:https://stackoverflow.com/questions/60359639/how-to-handle-different-messages-from-content-script-in-different-functions-of