make google extensions extension example developer create chrome apps javascript google-chrome google-chrome-extension google-chrome-app

javascript - google - Mensaje de extensión de Chrome pasando: respuesta no enviada



developer chrome apps (3)

Estoy tratando de pasar mensajes entre el script de contenido y la extensión

Esto es lo que tengo en script de contenido

chrome.runtime.sendMessage({type: "getUrls"}, function(response) { console.log(response) });

Y en el script de fondo tengo

chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) { if (request.type == "getUrls"){ getUrls(request, sender, sendResponse) } }); function getUrls(request, sender, sendResponse){ var resp = sendResponse; $.ajax({ url: "http://localhost:3000/urls", method: ''GET'', success: function(d){ resp({urls: d}) } }); }

Ahora si envío la respuesta antes de la llamada ajax en la función getUrls , la respuesta se envía con éxito, pero en el método de éxito de la llamada ajax cuando envío la respuesta no la envía, cuando voy a depurar puedo ver que el puerto es nulo dentro del código para la función sendResponse .


De la documentación para chrome.runtime.onMessage.addListener :

Esta función deja de ser válida cuando el detector de eventos retorna, a menos que devuelva verdadero del detector de eventos para indicar que desea enviar una respuesta de forma asíncrona (esto mantendrá el canal de mensajes abierto hasta el otro extremo hasta que se llame a sendResponse).

Entonces solo necesitas agregar el return true; después de la llamada a getUrls para indicar que llamarás a la función de respuesta de forma asíncrona.


La respuesta aceptada es correcta, solo quería agregar un código de muestra que simplifica esto. El problema es que la API (en mi opinión) no está bien diseñada porque nos obliga a los desarrolladores a saber si un mensaje en particular se manejará como sincronizado o no. Si maneja muchos mensajes diferentes, esto se convierte en una tarea imposible porque nunca se sabe si en el fondo de alguna función, un sendResponse pasado se llamará asincrónico o no. Considera esto:

chrome.extension.onMessage.addListener(function (request, sender, sendResponseParam) { if (request.method == "method1") { handleMethod1(sendResponse); }

¿Cómo puedo saber si en el fondo handleMethod1 la llamada será asincrónica o no? ¿Cómo puede alguien que modifique handleMethod1 saber que romperá una llamada introduciendo algo asincrónico?

Mi solución es esta:

chrome.extension.onMessage.addListener(function (request, sender, sendResponseParam) { var responseStatus = { bCalled: false }; function sendResponse(obj) { //dummy wrapper to deal with exceptions and detect async try { sendResponseParam(obj); } catch (e) { //error handling } responseStatus.bCalled= true; } if (request.method == "method1") { handleMethod1(sendResponse); } else if (request.method == "method2") { handleMethod2(sendResponse); } ... if (!responseStatus.bCalled) { //if its set, the call wasn''t async, else it is. return true; } });

Esto maneja automáticamente el valor de retorno, independientemente de cómo elija manejar el mensaje. Tenga en cuenta que esto supone que nunca olvida llamar a la función de respuesta. También tenga en cuenta que Chrome podría haber automatizado esto para nosotros, no veo por qué no lo hicieron.


Puede usar mi biblioteca https://github.com/lawlietmester/webextension para hacer que esto funcione tanto en Chrome como en FF con Firefox sin retrollamadas.

Tu código se verá así:

Browser.runtime.onMessage.addListener( request => new Promise( resolve => { if( !request || typeof request !== ''object'' || request.type !== "getUrls" ) return; $.ajax({ ''url'': "http://localhost:3000/urls", ''method'': ''GET'' }).then( urls => { resolve({ urls }); }); }) );