sendResponse в Port.postmessage () - PullRequest
       18

sendResponse в Port.postmessage ()

0 голосов
/ 19 апреля 2020

У меня есть следующий код

browser.runtime.onConnect.addListener(function (externalPort) {
    externalPort.onMessage.addListener((message, sender, sendResponse) => {
      sendResponse(42);
    }
});

Однако, похоже, что слушатели для Port.onMessage не получают вызов с sendResponse в качестве слушателей для browser.runtime.onMessage.

Любой Идея, как отправлять ответы на сообщения в порты?

Ответы [ 2 ]

1 голос
/ 20 апреля 2020

Обмен сообщениями на основе порта не использует sendResponse. Просто отправьте другое сообщение в порт.

Вот очень упрощенный пример системы обмена сообщениями на основе портов. Он не передает ошибки или исключения, не имеет времени ожидания. Идея состоит в том, чтобы передать id, сохранить обратный вызов для идентификатора на карте и использовать тот же идентификатор в ответе для вызова этого сохраненного обратного вызова.

В отличие от browser.runtime.sendMessage, который создает новый порт каждый раз (относительно дорогая операция, если вы отправляете много сообщений), мы повторно используем один и тот же порт.

отправитель:

const port = browser.runtime.connect({name: 'foo'});
const portMap = new Map();
let portMessageId = 0;

port.onMessage.addListener(msg => {
  const {id, data} = msg;
  const resolve = portMap.get(id);
  portMap.delete(id);
  resolve(data);
});

function send(data) {
  return new Promise(resolve => {
    const id = ++portMessageId;
    portMap.set(id, resolve);
    port.postMessage({id, data});
  });
}

использование:

(async () => {
  const response = await send({foo: 'whatever'});
  console.log(response);
})();

получатель:

/** @param {chrome.runtime.Port} port */
browser.runtime.onConnect.addListener(port => {
  if (port.name === 'foo') {
    port.onMessage.addListener(msg => {
      const {id, data} = msg;
      port.postMessage({id, data: processMessage(data)});
    });
  }
});
1 голос
/ 20 апреля 2020

Port.postMessage() - это метод обмена сообщениями только для pu sh, поэтому вам нужно использовать обычный метод runtime.sendMessage() параллельно. Вот пример:

манифест. json:

{
  "name": "panel example",
  "version": "1",
  "manifest_version": 2,
  "background": {
    "scripts": ["background.js"]
  },
  "browser_action": {
    "default_title": "panel",
    "default_popup": "panel.html"
  },
  "permissions": [
    "tabs"
  ]
}

фон. js:

browser.runtime.onConnect.addListener(port => {
  let tabId;
  const listenerForPort = (message, sender) => {
    if (message &&
        typeof message == 'object' &&
        message.portName == port.name) {
      switch (message.type) {
        case 'get-tabId':
          return Promise.resolve(tabId);
      }
    }
  };
  browser.runtime.onMessage.addListener(listenerForPort);
  port.onMessage.addListener(message => {
    if (message &&
        typeof message == 'object' &&
        message.tabId)
      tabId = message.tabId;
  });
  port.onDisconnect.addListener(port => {
    browser.runtime.onMessage.removeListener(listenerForPort);
    if (tabId)
      browser.tabs.remove(tabId);
  });
});

панель. html:

<!DOCTYPE html>
<script type="application/javascript" src="panel.js"></script>
<button id="button">Click Me</button>

панель. js:

browser.windows.getCurrent({ populate: true }).then(win => {
  const portName = `port for window ${win.id}`;
  const activeTab = win.tabs.find(tab => tab.active);
  const port = browser.runtime.connect({
    name: portName
  });
  port.postMessage({ tabId: activeTab.id });

  const button = document.getElementById('button');
  button.addEventListener('click', async event => {
    const tabIdFromBackground = await browser.runtime.sendMessage({
      type: 'get-tabId',
      portName
    });
    button.textContent = tabIdFromBackground;
  });
});

В этом примере имеется прослушиватель, соответствующий соединению, и он предназначен для ответа только на сообщения, отправленные с соответствующим именем порта.

...