原则

如官网说的

If multiple pages are listening for onMessage events, only the first to call sendResponse() for a particular event will succeed in sending the response. All other responses to that event will be ignored.

For new extensions you should prefer promises over callbacks. If you’re using callbacks, the sendResponse() callback is only valid if used synchronously, or if the event handler returns true to indicate that it will respond asynchronously. The sendMessage() function’s callback will be invoked automatically if no handlers return true or if the sendResponse() callback is garbage-collected.

多个 Listener 之间如何确定该返回那个 Listener 的执行结果,是通过谁先调用 sendResponse 并且有返回值判断的,这也就意味着我们需要保证每个 Listener 未处理逻辑是,需要保证没有返回值,比如下面这种.

browser.runtime.onMessage.addListener((payload, sender, res) => {
  if (payload.type === "foo") {
    return "bar";
  }
});

注意

如果你的 Listener 需要处理异步逻辑,请不要按以下写.

//  这是一个错误的例子,如果我们的 listener 是 async function 那么默认就有一个返回值是 Promise<void>
browser.runtime.onMessage.addListener(async (payload) => {
  if (payload.type === "reload") {
    return await reload();
  }
});

下面这个才是正确的写法

browser.runtime.onMessage.addListener((payload, sender, sendResponse) => {
  if (payload.type === "reload") {
    reload().then((res) => {
      sendResponse(res);
    });
    return true;
  }
});

直接上代码

实现起来很简单,就跟 DOM 事件监听一样,只需要写多个监听器就行了

//  background.js
browser.runtime.onMessage.addListener((payload, sender, res) => {
  if (payload.id === "foo") {
    setTimeout(() => {
      res("bar");
    }, 1000);
    return true;
  }
});

browser.runtime.onMessage.addListener((payload) => {
  if (payload.type === "reload") {
    return reload();
  }
});