¿Cómo manejar “Runtime.lastError no verificado: el puerto de mensajes se cerró antes de que se recibiera una respuesta”?

5 minutos de lectura

avatar de usuario
bongoSLAP

Perdóneme por los errores evidentes, ya que soy nuevo en las extensiones de Chrome, pero este error con la API de paso de mensajes de Chrome se ha discutido aquí, aquíy aquí en el pasado y la respuesta común es similar a ‘deshabilitar las extensiones de Chrome existentes, una de ellas está causando el error’. ¿Es esto lo mejor que se puede lograr? ¿Se supone que debemos darnos la vuelta y aceptar el hecho de que nuestras extensiones entrarán en conflicto con otras? Devolver verdadero o devolver una Promesa para la función de devolución de llamada del oyente y usar sendResponse no me resuelve el problema.

Actualmente, solo puedo obtener el nuevo valor almacenado en chrome.storage.local (sin errores) por deshabilitando todas las demás extensiones de Chrome, eliminando la extensión y cargando una copia de seguridad de la extensión desempaquetada. Curiosamente, el código solo parece funcionar en developer.chrome.com, no funciona en absoluto en las otras URL de “coincidencias” en manifest.json.

Creo que hay algún significado en el await y async operadores para resolver este problema, pero no estoy seguro de cómo implementarlo correctamente.

manifiesto.json:

{
    "manifest_version": 2,
    "name": "my extension",
    "version": "1.0",
    "description": "its my extension",
    "permissions": [
        "declarativeContent", 
        "storage", 
        "activeTab"
    ],
    "content_scripts": [
        {
          "matches": [
            "*://developer.chrome.com/*",
            "*://bbc.co.uk/*",
            "*://theguardian.com/*",
            "*://dailymail.co.uk/*"
          ],
          "js": ["content.js"]
        }
      ],
    "background": {
      "scripts": ["background.js"],
      "persistent": false
    },
    "content_security_policy": "script-src 'self' https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js; object-src 'self'",
    "page_action": {
        "default_popup": "popup.html"
    },
    "icons": {
        "16": "images/icon16.png",
        "32": "images/icon32.png",
        "48": "images/icon48.png",
        "128": "images/icon128.png"
      }
}

ventana emergente.html:

<!DOCTYPE html>
  <html>
    <head>
      <title>my extension</title>
      <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
      <script src="popup.js"></script>
      <link rel="stylesheet" type="text/css" href="style.css">
    </head>
    <body>
      <h1>my extension</h1>
      <h2>Article: <span id="article-headline"></span></h2>
      <button id="detect-article">Detect Article</button>
    </body>
  </html>

ventana emergente.js:

$(document).ready(function() {
    $("#detect-article").click(function() {
        chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
            chrome.tabs.sendMessage(tabs[0].id, {request: "Requesting headline"}, function(response) {
                console.log("Requesting headline")
            });
        });
    });    
})

function getHeadline(changes) {
    let changedValues = Object.keys(changes);
    //console.log(changedValues);

    for (var item of changedValues) {
        console.log("new value: " + changes[item].newValue);
        $("#article-headline").text(changes[item].newValue)
    }
}

chrome.storage.onChanged.addListener(getHeadline);

contenido.js:

function handleRequest(message, sender, sendResponse) {
    console.log("Request recieved");
    let headlineList = document.getElementsByTagName("h1");
    chrome.storage.local.set({headline: headlineList[0].innerText}, function() {
        console.log("'" + headlineList[0].innerText + "' stored in local storage");
    });
    return true;
}

chrome.runtime.onMessage.addListener(handleRequest);

fondo.js:

chrome.runtime.onInstalled.addListener(function() {
    chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
      chrome.declarativeContent.onPageChanged.addRules([{
        conditions: [
          new chrome.declarativeContent.PageStateMatcher({
            pageUrl: { hostContains: 'developer.chrome.com' },
          }),
          new chrome.declarativeContent.PageStateMatcher({
            pageUrl: { hostContains: 'bbc.co.uk' },
          }),
          new chrome.declarativeContent.PageStateMatcher({
            pageUrl: { hostContains: 'theguardian.com' },
          }),
          new chrome.declarativeContent.PageStateMatcher({
              pageUrl: { hostContains: 'dailymail.co.uk' },
          }),
        ],
      actions: [new chrome.declarativeContent.ShowPageAction()]
    }]);
  });
});

Muchas gracias por tomarse el tiempo de mirar/volver a mirar este problema, las soluciones relacionadas con las ‘deshabilitar extensiones existentes’ antes mencionadas no son lo que estoy buscando.

  • Su script de contenido nunca llama sendResponse aunque la ventana emergente está esperando una respuesta.

    – Tito

    26 de enero de 2020 a las 0:11

  • ¿Has logrado que funcione correctamente usando sendResponse? cuando lo probé el error persistió. Gracias.

    – bongo SLAP

    26 de enero de 2020 a las 2:09

avatar de usuario
wOxxOm

Cuando especifica una devolución de llamada para sendMessage, le está diciendo a la API que NECESITAS una respuesta así que cuando su secuencia de comandos de contenido no responde usando sendResponse, la API piensa que sucedió algo terrible y lo informa como tal.

Recordatorio: al editar secuencias de comandos de contenido, asegúrese de volver a cargar tanto la extensión en chrome://extensions página y las pestañas que debe tener este script de contenido.

No necesitas ninguna respuesta:

  • Eliminar la devolución de llamada en sendMessage

    chrome.tabs.sendMessage(tabs[0].id, {request: "Requesting headline"});
    
  • Remover return true – todo lo que hace actualmente es decirle a la API que mantenga el puerto de mensajería abierto indefinidamente, que nunca será utilizado por usted, por lo que es solo una fuente de pérdida de memoria.

    chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
      // do something
      // don't return true
      // ManifestV2: don't call sendResponse
      // ManifestV3 bug: uncomment the next line
      // sendResponse();
    });
    

    En ManifestV3, debido a un error en Chrome 99+, necesita una llamada ficticia de sendResponse().

Necesitas una respuesta:

  • Reemplazar return true con sendResponse

    chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
      sendResponse('whatever');
    });
    

Necesita una respuesta del código que se ejecuta de forma asíncrona como chrome Devolución de llamada de la API:

  • Mantenerse return true

  • Llamar sendResponse(someImportantData) dentro de la devolución de llamada

    chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
      chrome.storage.local.set({foo: 'bar'}, () => {
        sendResponse('whatever');
      });
      return true;
    });
    

  • Ya veo. Me las arreglé para que funcione ahora, usted se las arregló para dar la mejor idea de este problema recurrente. Muchas gracias. 🙂

    – bongo SLAP

    26 de enero de 2020 a las 23:18

  • Esta es absolutamente la mejor respuesta que me ayudó a resolver este problema, que tomó demasiado tiempo para encontrar información útil. Eliminé mis funciones de devolución de llamada vacías y mi consola está limpia nuevamente.

    – r14n

    1 de octubre de 2020 a las 1:51

  • Uso la aplicación struts 1 con iframes y js, jsp, html. mi aplicación funciona en IE pero por encima de los problemas de tiempo de ejecución en Chrome. Me podrías orientar donde exactamente tengo que colocar esta pieza. El archivo js principal colocado no parece cargar ese contenido. cualquier ayuda muy apreciada.

    – satvidtech

    16 de diciembre de 2021 a las 7:35

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad