Extensión de Chrome: el código dentro de chrome.runtime.onMessage.addListener nunca se ejecuta
Tengo muchos problemas para intentar pasar una variable de un script de contenido a popup.js usando el método sendMessage.
Este es el script de contenido donde estoy enviando un mensaje al script de fondo que contiene la cantidad de elementos secundarios de un nodo DOM:
let incomingChatsNumber = incomingChatsContainer.children().length;
chrome.runtime.sendMessage({ incomingChatsNumber: incomingChatsNumber });
Luego, background.js escucha el mensaje y envía un mensaje con la misma variable a popup.js:
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
let incomingChatsNumber = message.incomingChatsNumber;
chrome.runtime.sendMessage({ incomingChatsNumber: incomingChatsNumber });
});
En el popup.js tengo un botón que activará algún código si el "IncomingChatsNumber" es mayor que 0 (el contenedor dom tiene hijos):
$("#js-toggleSorting").on("click", function () {
chrome.runtime.onMessage.addListener(function (message) {
let incomingChatsNumber = message.incomingChatsNumber;
if (incomingChatsNumber <= 0) {
$(".message").html("<p>No Chats To Sort, You Joker</p>");
} else {
$(".message").html("<p>Sorting Chats</p>");
//This code never gets executed
if ($("#js-toggleSorting").attr("data-click-state") == 1) {
$("#js-toggleSorting").attr("data-click-state", 0);
$("#js-toggleSorting").html("SORT INCOMING CHATS");
sortFunction(false);
} else {
$("#js-toggleSorting").attr("data-click-state", 1);
$("#js-toggleSorting").html("STOP SORTING INCOMING CHATS");
sortFunction(true);
}
save_button_state();
}
});
});
Lo extraño para mí es que popup.js obtiene el valor correcto, incluso puedo consolarlo. Iniciar sesión, pero tan pronto como pongo más código en eso, si es condicional, el código nunca se ejecuta, incluso cuando la condición está bien.
ACTUALIZAR:
Después de hacer las modificaciones sugeridas por ehab, me di cuenta de que la variable está "indefinida" todo el tiempo debido a la naturaleza asíncrona de chrome.runtime.onMessage.addListener:
Guión de contenido:
let incomingChatsNumber = incomingChatsContainer.children().length;
chrome.runtime.sendMessage({ incomingChatsNumber: incomingChatsNumber });
Fondo.js:
chrome.runtime.onMessage.addListener(function (message) {
let incomingChatsNumber = message.incomingChatsNumber;
chrome.runtime.sendMessage({ incomingChatsNumber: incomingChatsNumber });
});
Popup.js (Aquí es donde necesito usar el valor de la variable incomingChatsNumber):
let latestIncomingChatsNumber;
chrome.runtime.onMessage.addListener(function (message) {
let incomingChatsNumber = message.incomingChatsNumber;
latestIncomingChatsNumber = incomingChatsNumber;
//This Works
console.log(latestIncomingChatsNumber);
});
//This will give me an undefined value
console.log(latestIncomingChatsNumber);
Entiendo que mi problema está relacionado con el hecho de que las API de chrome.* son asíncronas, por lo que chrome.runtime... y console.log(...) se ejecutarán al mismo tiempo, de ahí el error. Entonces, ¿cómo usar la variable LatestIncomingChatsNumber dentro de un evento de clic? ¿Tengo que guardar primero "latestIncomingChatsNumber" en el almacenamiento local dentro de chrome.runtime.onMessage.addListener?
Respuestas
No debe colocar un detector de eventos dentro de otro controlador de eventos, esta es una práctica extremadamente mala, incluso si hace lo que cree que debería estar haciendo, esto causará pérdidas de memoria en el futuro y hará que el código sea difícil de leer y semánticamente. incorrecto.
Al mirar su código, parece que el problema es que el controlador del mensaje recibe varias llamadas debido a los detectores de eventos anteriores agregados en el evento de clic.
let latestIncomingChatsNumber
chrome.runtime.onMessage.addListener(function (message) {
let incomingChatsNumber = message.incomingChatsNumber;
// save this into the application state, i will use a parent scope variable you could use something else
latestIncomingChatsNumber = incomingChatsNumber
});
$("#js-toggleSorting").on("click", function () {
if (latestIncomingChatsNumber <= 0) {
$(".message").html("<p>No Chats To Sort, You Joker</p>");
} else {
$(".message").html("<p>Sorting Chats</p>");
//This code never gets executed
if ($("#js-toggleSorting").attr("data-click-state") == 1) {
$("#js-toggleSorting").attr("data-click-state", 0);
$("#js-toggleSorting").html("SORT INCOMING CHATS");
sortFunction(false);
} else {
$("#js-toggleSorting").attr("data-click-state", 1);
$("#js-toggleSorting").html("STOP SORTING INCOMING CHATS");
sortFunction(true);
}
save_button_state(); // i believe this function saves the attributes to the dom elements
}
});
si save_button_state
hace un buen trabajo, el código que compartí debería funcionar