ส่วนขยายของ Chrome: โค้ดภายใน chrome.runtime.onMessage.addListener จะไม่ถูกเรียกใช้งาน

Aug 18 2020

ฉันมีปัญหามากในการพยายามส่งตัวแปรจากสคริปต์เนื้อหาไปยัง popup.js โดยใช้เมธอด sendMessage

นี่คือสคริปต์เนื้อหาที่ฉันส่งข้อความไปยังสคริปต์พื้นหลังที่มีจำนวนลูกของโหนด 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 });
});

ในป๊อปอัป 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 ฉันตระหนักว่าตัวแปรนั้น "ไม่ได้กำหนด" ตลอดเวลาเนื่องจากลักษณะ async ของ 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. * APIs เป็นแบบอะซิงโครนัสดังนั้น chrome.runtime ... และ console.log (... ) จะถูกดำเนินการในเวลาเดียวกันดังนั้นจึงเกิดข้อผิดพลาด ดังนั้นจะใช้ตัวแปร 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ทำงานได้ดีรหัสที่ฉันแชร์ควรใช้งานได้