如何在后台脚本的不同功能中处理不同的消息(来自内容脚本)? [英] How to handle different messages (from content script) in different functions of background script?

查看:88
本文介绍了如何在后台脚本的不同功能中处理不同的消息(来自内容脚本)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的chrome扩展程序的内容脚本具有两个事件侦听器功能.这两个函数将不同的变量作为消息发送.因此,如果后台脚本想要区分这些事件/变量,该怎么办?

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.

当前,我从每个函数发送一个id 1和2(以及到后台脚本的消息),并使用if-else来区分哪个消息来自哪个函数.我认为这不是一个非常优雅的解决方案.

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.

内容脚本:

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
});
}

背景脚本:

chrome.runtime.onMessage.addListener(receiver);
function receiver(request, sender, sendResponse) {
if (request.id == 1) {
// code
}
else if (request.id == 2) {
// code
}

推荐答案

idcmdactionmethod属性与实际值一起发送是标准解决方案,没有更好的解决方案从概念上讲.您可以使用id: 'clicked'id: 'changed'代替数字索引.

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.

就装饰性的解决方案"而言,您可以使用Proxy API包装chrome.runtime.sendMessage,例如将其包装为HQ(总部")对象:

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());
  }
}

为此,首先让我们在内容脚本中定义HQ:

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();
  },

};

...和一个听众:

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扩展程序库实现了类似的方法.

There are libraries for chrome extensions that implement a similar approach.

这篇关于如何在后台脚本的不同功能中处理不同的消息(来自内容脚本)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆