Как передать сообщения в расширении Chrome из content.js в background.js в popup.js?

Я хочу написать расширение Chrome, которое по сути должно передавать информацию (1) из сценария content.js в background.js, где оно отправляет информацию на внешний сервер Node.js, а затем (2) background.js должно пересылать ответ сервера на popup.js, поэтому его можно отобразить в popup.html. Этот процесс должен происходить каждый раз при посещении страницы.

Я добился того, что информация полностью передается в popup.js, но я использую chrome.runtime.sendMessage каждый раз для передачи информации от контента к фону и оттуда во всплывающее окно, и в каждом случае я использую chrome.runtime.onMessage.addListener для получения сообщения. Однако теперь popup.js получает как сообщение, которое content.js передает в background.js, так и сообщение, правильно переданное из background.js в popup.js. Я просто хочу, чтобы последнее сообщение было получено popup.js.

Это мой background.js код:

chrome.runtime.onMessage.addListener(
    function(request, sender, sendResponse) {

        console.info("received from content.js:\n" + request.content_message);
    
        sendResponse({check: "to content.js: background recieved content_message"});

        fetch('http://localhost:3000/message', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ message: request.content_message})
        })
        .then(response => response.json())
        .then(data => {
            console.info(data.response);

            const to_popup = data.response;

            chrome.runtime.sendMessage({res: to_popup }, function(response) {
                console.info(response.popup_answer);
            });
        })
        .catch(error => {
            console.error('Error:', error);
        });
    }
);

А это мой popup.js код:

chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) {
  alert(JSON.stringify({request}));

  sendResponse({popup_answer: "to background: popup recieved message"});
});

Я сравнил свой код с ответом, представленным здесьздесь . Я посмотрел сообщение в доках и там написано:

Если несколько страниц прослушивают события onMessage, только первая, вызвавшая sendResponse() для определенного события, сможет отправить ответ. Все остальные ответы на это событие будут игнорироваться.

Кажется, это касается только случая ответа, но не получения сообщений.

Я думал о

  1. наличие popup.js фильтрует отправителя каждого сообщения и что-то с ним делает только в том случае, если отправитель является фоновым,
  2. создание долговременной связи между фоном и всплывающим окном.

Мне кажется, что должен быть лучший и разумный способ. Есть ли у вас какие-либо предложения для меня? Спасибо!

Нет необходимости в фоновом скрипте: просто делайте все в onMessage во всплывающем окне.

woxxom 01.07.2024 21:02

@woxxom Спасибо! Но мне нужен фоновый скрипт для подключения и получения ответа от сервера, так как это должно происходить автоматически. Когда я реализовал это во всплывающем окне, это больше не будет автоматическим, или есть обходной путь?

user25899957 01.07.2024 21:31

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

woxxom 01.07.2024 21:53

@woxxom Спасибо, я сделал это сейчас аналогично тому, что вы предложили, и все работает отлично :) Это мне действительно помогло!

user25899957 02.07.2024 21:28
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
4
75
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете использовать что-то вроде этого:

// constants.js
export const backgroundScriptCommands = {
  FETCH_DATA_FROM_SERVER: 'fetch-data-from-server',
  ...
};
export const popupCommands = {
  PRINT_DATA: 'print-data',
  ...
};

// Your content-script.js
chrome.runtime.sendMessage({ type: backgroundScriptCommands.FETCH_DATA_FROM_SERVER });

// Your background-script.js
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  switch (request.type) {
    case backgroundScriptCommands.FETCH_DATA_FROM_SERVER:
      // do something
  }
});

// Your popup.js
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  switch (request.type) {
    case popupCommands.PRINT_DATA:
      // do something
  }
});

Таким образом вы сможете понять, кому адресовано сообщение, и просто не реагировать, если сообщение адресовано, например background-script.

Однако здесь есть несколько моментов, на которые стоит обратить ваше внимание: chrome.runtime.onMessage прослушиватель в вашем popup.js будет работать только после того, как пользователь нажмет на всплывающий значок. И перестанет работать, если всплывающее окно закроется. Возможно, вы можете просто использовать popup.js, чтобы поработать, как написал @woxxom в комментариях, или просто отправить сообщение service-workerchrome.runtime.sendMessage({ type: backgroundScriptCommands.FETCH_DATA_FROM_SERVER }). И еще: если вы попытаетесь отправить сообщение с background-script на popup.js, если оно неактивно, вы получите исключение.

Большое спасибо! Я сделал это сейчас, как предложил @woxxom. Вы очень хорошо заметили, что popup.js работает сразу после того, как пользователь нажимает на значок всплывающего окна. Мне это не подошло бы, так что большое спасибо за подсказку!

user25899957 02.07.2024 21:27

Другие вопросы по теме