首页 > 解决方案 > Chrome 扩展:chrome.runtime.onMessage.addListener 中的代码永远不会被执行

问题描述

尝试使用 sendMessage 方法将变量从内容脚本传递到 popup.js 时遇到了很多麻烦。

这是我向后台脚本发送消息的内容脚本,其中包含 DOM 节点的子节点数量:

let incomingChatsNumber = incomingChatsContainer.children().length;
chrome.runtime.sendMessage({ incomingChatsNumber: incomingChatsNumber });

然后 background.js 监听消息并将带有相同变量的消息本身发送到 popup.js:

chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
  let incomingChatsNumber = message.incomingChatsNumber;
  chrome.runtime.sendMessage({ incomingChatsNumber: incomingChatsNumber });
});

在 popup.js 中,我有一个按钮,如果“incomingChatsNumber”大于 0(dom 容器有孩子),它将触发一些代码:

  $("#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();
      }
    });
  });

对我来说奇怪的是,popup.js 获得了正确的值,我什至可以对其进行控制台记录,但是一旦我在上面添加更多代码,如果有条件,即使条件可以执行,代码也永远不会被执行。

更新:

在进行了 ehab 建议的修改后,我意识到由于 chrome.runtime.onMessage.addListener 的异步性质,该变量一直是“未定义的”:

内容脚本:

  let incomingChatsNumber = incomingChatsContainer.children().length;
  chrome.runtime.sendMessage({ incomingChatsNumber: incomingChatsNumber });

背景.js:

chrome.runtime.onMessage.addListener(function (message) {
  let incomingChatsNumber = message.incomingChatsNumber;
  chrome.runtime.sendMessage({ incomingChatsNumber: incomingChatsNumber });
});

Popup.js(这是我需要使用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);

我知道我的问题与 chrome.* API 是异步的这一事实有关,因此 chrome.runtime... 和 console.log(...) 将同时执行,因此出现错误。那么如何在点击事件中使用 latestIncomingChatsNumber 变量呢?我是否必须先将“latestIncomingChatsNumber”保存到 chrome.runtime.onMessage.addListener 内的本地存储中?

标签: javascriptjquerygoogle-chrome-extension

解决方案


您不应该将事件侦听器放在另一个事件处理程序中,即使它做了您认为应该做的事情,这也是一种非常糟糕的做法,这将导致您在路上发生内存泄漏,并使代码难以阅读和语义不正确。

似乎基于查看您的代码,问题在于消息的处理程序被多次调用,因为在单击事件中添加了先前的事件侦听器

 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
      }
  });

如果save_button_state做得好我共享的代码应该可以工作


推荐阅读