Chrome拡張機能:chrome.runtime.onMessage.addListener内のコードが実行されることはありません

Aug 18 2020

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が正しい値を取得することです。それをconsole.logすることもできますが、条件付きの場合は、条件が整っていてもコードが実行されないように、コードを追加するとすぐに実行されます。

更新:

ehabによって提案された変更を行った後、chrome.runtime.onMessage.addListenerの非同期性のために、変数が常に「未定義」であることに気付きました。

コンテンツスクリプト:

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

Background.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(...)が同時に実行されるため、エラーが発生することに関連していることがわかりました。では、on clickイベント内でlatestIncomingChatsNumber変数を使用するにはどうすればよいですか?最初に「latestIncomingChatsNumber」をchrome.runtime.onMessage.addListener内のロー​​カルストレージに保存する必要がありますか?

回答

1 ehab Aug 18 2020 at 21:41

イベントリスナーを別のイベントハンドラー内に配置しないでください。これは、想定どおりに実行されたとしても非常に悪い方法です。これにより、将来的にメモリリークが発生し、コードが読みにくくなり、セマンティックになります。正しくありません。

コードを見ると、クリックエベットに以前のイベントリスナーが追加されているために、メッセージのハンドラーが複数回呼び出されることが問題のようです。

 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私が共有したコードがうまくいくなら、うまくいくはずです