Ekstensi Chrome: Kode di dalam chrome.runtime.onMessage.addListener tidak pernah dijalankan

Aug 18 2020

Saya mengalami banyak masalah saat mencoba meneruskan variabel dari skrip konten ke popup.js menggunakan metode sendMessage.

Ini adalah skrip konten tempat saya mengirim pesan ke skrip latar belakang yang berisi jumlah anak dari simpul DOM:

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

Kemudian background.js mendengarkan pesan tersebut dan mengirim pesan itu sendiri dengan variabel yang sama ke popup.js:

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

Di popup.js saya memiliki tombol yang akan memicu beberapa kode jika "incomingChatsNumber" lebih dari 0 (wadah dom memiliki anak):

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

Hal yang aneh bagi saya adalah bahwa popup.js mendapatkan nilai yang benar, saya bahkan dapat membuat konsol.log, tetapi segera setelah saya memasukkan lebih banyak kode, jika kondisional kode tidak pernah dijalankan bahkan ketika kondisinya baik-baik saja.

MEMPERBARUI:

Setelah melakukan modifikasi yang disarankan oleh ehab, saya menyadari bahwa variabel tersebut "tidak ditentukan" sepanjang waktu karena sifat asinkron dari chrome.runtime.onMessage.addListener:

Isi Script:

  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 (Di sinilah saya perlu menggunakan nilai variabel 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);

Saya mengerti bahwa masalah saya terkait dengan fakta bahwa chrome. * API tidak sinkron sehingga chrome.runtime ... dan console.log (...) akan dijalankan pada saat yang sama, oleh karena itu terjadi kesalahan. Jadi bagaimana cara menggunakan variabel latestIncomingChatsNumber di dalam event on click? Apakah saya harus menyimpan "latestIncomingChatsNumber" ke penyimpanan lokal di dalam chrome.runtime.onMessage.addListener terlebih dahulu?

Jawaban

1 ehab Aug 18 2020 at 21:41

Anda tidak boleh meletakkan event listener di dalam event handler lain, ini adalah praktik yang sangat buruk bahkan jika itu melakukan apa yang menurut Anda seharusnya dilakukan, ini akan menyebabkan kebocoran memori di masa mendatang, dan membuat kode sulit untuk dibaca dan secara semantik salah.

Tampaknya berdasarkan melihat kode Anda, masalahnya adalah bahwa penangan untuk pesan dipanggil beberapa kali karena event listener sebelumnya ditambahkan di klik evet.

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

jika save_button_statemelakukan pekerjaan dengan baik, kode yang saya bagikan harus berfungsi