Отправка свойства id
или cmd
или action
или method
вместе с фактическим значением является стандартным решением, концептуально лучшего нет. Вы можете использовать id: 'clicked'
и id: 'changed'
вместо числовых c индексов.
Что касается космеций c "решений" go, вы можете использовать Proxy
API для переноса sendMessage, например, в объекте HQ
("штаб-квартира"):
async function queryHQ() {
if (await HQ.test(1, 2, 3) === 123) {
console.log('ok!');
} else {
console.log(await HQ.download());
}
}
Чтобы это работало, сначала давайте определим HQ
:
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)))
});
И обработаем его в фоновый скрипт использует карту команд:
const handlers = {
test(a, b, c) {
console.log(a, b, c);
return 123;
},
async download() {
return (await fetch(this.url)).text();
}
};
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);
}
});
Существуют библиотеки для chrome расширений, которые реализуют аналогичный подход.