Не отмечено runtime.lastError: порт сообщения закрыт до получения ответа. Расширение Chrome

Я получаю эту ошибку снова и снова и до сих пор не могу понять, как ее решить. Функция sendResponse вызывается до того, как функция analyzePageGuest завершила свое выполнение, но я не могу это исправить. Проект, который я делаю, представляет собой расширение для обнаружения фишинга с использованием API Virus Total. Вот что я пробовал: Может ли кто-нибудь мне помочь?

фон.js

async function analyzePageGuest(tabId, changeInfo, tab) {
  const url = tab.url
  console.info('URL:', url)
  let analysisIdValue
  try {
    const options = {
      method: 'POST',
      headers: {
        accept: 'application/json',
        'x-apikey':
          'apikey',
        'content-type': 'application/x-www-form-urlencoded',
      },
      body: new URLSearchParams({ url: url }),
    }

    fetch(
      'https://cors-anywhere.herokuapp.com/https://www.virustotal.com/api/v3/urls',
      options
    )
      .then((response) => response.json())
      .then((response) => {
        console.info(response)
        analysisIdValue = response.data.id
        console.info(analysisIdValue)
      })
      .catch((err) => console.error(err))

    // Wait for the analysis to complete using a polling mechanism
    let resultResponse
    let retries = 0
    let resultJson
    while (retries < 5) {
      await new Promise((resolve) => setTimeout(resolve, 2000)) // wait for 2 seconds
      resultResponse = await fetch(
        `https://cors-anywhere.herokuapp.com/https://www.virustotal.com/api/v3/analyses/${analysisIdValue}`,
        {
          method: 'GET',
          headers: {
            'x-apikey':
              'apikey',
          },
        }
      )
      resultJson = await resultResponse.json()
      if (resultJson.data.attributes.status === 'completed') {
        break
      }
      retries++
    }

    if (resultResponse.ok) {
      const malicious = resultJson.data.attributes.stats.malicious > 0
      const resultText = malicious
        ? 'Phishing detected!'
        : 'Safe from phishing :)'
      return resultText // Return the result text
    } else {
      return 'Error: Analysis failed' // Return an error message
    }
  } catch (error) {
    console.error('Error analyzing page:', error)
    return 'Error: Analysis failed' // Return an error message
  }
}

chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
  if (request.action === 'analyzePageGuest') {
    let tabId
    if (sender.tab) {
      tabId = sender.tab.id
    } else {
      const tabs = await chrome.tabs.query({
        active: true,
        currentWindow: true,
      })
      if (tabs.length > 0) {
        tabId = tabs[0].id
      } else {
        console.info('No tabs found!')
        sendResponse({ result: 'No tabs found!' }) // Return an error message
        return false
      }
    }
    if (tabId) {
      console.info('Tab ID:', tabId)
      const tab = await chrome.tabs.get(tabId)
      console.info('Tab URL:', tab.url)
      try {
        const resultText = await analyzePageGuest(tabId, {}, tab)
        console.info('Result text:', resultText)
        sendResponse({ result: resultText })
      } catch (error) {
        console.error('Error analyzing page:', error)
        sendResponse({ result: 'Error analyzing page' })
      }
    }
    return true
  }
})

всплывающее окно.js

const button = document.querySelector('.button')
const resultElement = document.getElementById('result')

button.addEventListener('click', () => {
  chrome.runtime.sendMessage({ action: 'analyzePageGuest' }, (response) => {
    if (response && response.result) {
      console.info('Received response:', response)
      resultElement.innerText = response.result
    }
  })

  setTimeout(() => {
    if (!resultElement.innerText) {
      resultElement.innerText =
        'Analysis not completed. Please try again later.'
    }
  }, 4000)
})

всплывающее окно.html

<div class = "popup-container">
        <span id = "current-url"></span>
      <button class = "button">
        <span class = "submit">Analyze page</span>
        <span class = "loading"><i class = "fas fa-circle-notch fa-spin"></i></i></span>
        <span class = "check"><i class = "fa fa-check"></i></span>
      </button>
      <span id = "result"></span>
    </div>

Я уже добавил return true в асинхронную функцию, но она не работает..

Поведение ключевого слова "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) для оценки ваших знаний,...
1
0
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Так. Чтобы ваш код заработал, вам необходимо внести несколько очень важных изменений.

Ваша функция прослушивателя не должна быть асинхронной. Согласно документации:

Предупреждение: не добавляйте async к функции. Добавление async меняет смысл отправки асинхронного ответа с использованием обещания, что фактически аналогично sendResponse(true).

Это должно выглядеть так:

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {})

И самое важное! Вы все делаете правильно. Вы возвращаете true для обработки асинхронного ответа, но неправильно вызываете функцию sendResponse. Функция sendResponse должна вызываться после получения результата в Promise.then(response => sendResponse(response)).

Я не рассматривал логику вашей функции analyzePageGuest, но окончательная функция прослушивателя должна выглядеть примерно так:

async function getActiveTab() {
  const tabs = await chrome.tabs.query({ active: true });
  let activeTab = null;
  tabs?.forEach((tab) => {
    if (!activeTab || tab.lastAccessed > activeTab.lastAccessed) {
      activeTab = tab;
    }
  });
  return activeTab;
}

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  switch (request.action) {
    case 'analyzePageGuest':
      getActiveTab().then(activeTab => {
        analyzePageGuest(activeTab.id, {}, activeTab)
          .then(response => sendResponse(response))
          .catch(() => sendResponse({ result: 'Error analyzing page' }));
      });
      return true;
  }
});

Чтобы получить URL-адрес активной вкладки, у вас должно быть разрешение tabs на manifest.json:

// manifest.json
...
"permissions": [
  "tabs"
]
...

Спасибо за Ваш ответ! В итоге я сохранил результат в локальном хранилище, поэтому во всплывающем окне я просто извлекаю его с помощью Storage.get, но все равно спасибо за ответ!

Ale26 02.07.2024 05:45

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