How to handle different messages (from content script) in different functions of background script?

大兔子大兔子 提交于 2020-06-17 09:15:33

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!