title: Chrome Extension postMessage & Listener
body: <p>I am injecting a script in website DOM from my extension. The script accesses the DOM object &amp; returns using postMessage(). I then listen to this in content.js &amp; get the object. There's a function which injects these scripts in DOM &amp; expects the object to return. This function gets called 5 times &amp; expects 5 different objects. The 1st call gets executed successfully &amp; returns object1 in addListener. But after that the listener waits to execute all the 4 scripts &amp; holds the object in postMessage. Once entire extension is loaded then the addEventListener gets called in the end &amp; then it returns all 4 remaining objects.</p>
  <p>Why is this behaviour? And how do I get the object from the postMessage
  in the addListener without it getting held?</p>
  <pre class="lang-js prettyprint-override"><code>function temp(){
      var globalObject = `var globalObject = domObj; `;
      var scriptHtml = [
        globalObject,
        `var obj = JSON.parse(JSON.stringify(globalObject));`,
        `console.log(&quot;Obj in DOM&quot;,obj);`,
        `window.postMessage(obj)`,
      ].join(&quot;&quot;);
  
      s.innerHTML = scriptHtml;
  
      document.body.appendChild(s);
  
  var obj = {};
      window.addEventListener(
        &quot;message&quot;,
        function (event) {
          // We only accept messages from ourselves
          if (event.source != window) return;
          if (event.data) {
            obj = event.data;
            // console.log(&quot;Obj in Content.js &quot;, obj);
            // port.postMessage(event.data);
          }
        },
        false
      );
  return obj;
  }
  </code></pre>
  <p>The &quot;content.js&quot; script is called from &quot;background.js&quot;</p>
  <p>background.js</p>
  <pre class="lang-js prettyprint-override"><code>chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
      console.log(tabId, changeInfo, tab);
      if (changeInfo.status == 'complete') {
          Utils.executeScriptUsingTabId(tabId, 'content.js').catch(err =&gt; {
              console.log(err);
          });
      }
  });
  </code></pre>
  <p>manifest.json</p>
  <pre class="lang-json prettyprint-override"><code>{
      &quot;manifest_version&quot;: 2,
      &quot;name&quot;: &quot;My Ext&quot;,
      &quot;description&quot;: &quot;My Extension&quot;,
      &quot;version&quot;: &quot;5.0&quot;,
      &quot;icons&quot;: {
          &quot;128&quot;: &quot;images/icon.png&quot;
      },
      &quot;externally_connectable&quot;: {
          &quot;matches&quot;: [&quot;*://*.example.com/*&quot;, &quot;*://localhost/*&quot;]
      },
      &quot;permissions&quot;: [
          &quot;&lt;all_urls&gt;&quot;,
          &quot;webRequest&quot;,
          &quot;webRequestBlocking&quot;,
          &quot;tabs&quot;,
          &quot;http://*/*&quot;,
          &quot;https://*/*&quot;
      ],
      &quot;background&quot;: {
          &quot;page&quot;: &quot;background.html&quot;
      },
      &quot;browser_action&quot;: {
          &quot;default_title&quot;: &quot;My Extension&quot;,
          &quot;default_icon&quot;: &quot;images/icon.png&quot;,
          &quot;default_popup&quot;: &quot;popup.html&quot;
      },
      &quot;web_accessible_resources&quot;: [&quot;images/*.png&quot;, &quot;helpers/*.js&quot;]
  }
  </code></pre>
  <p>content.js</p>
  <pre class="lang-js prettyprint-override"><code>console.time(&quot;start&quot;);
  
  import getPageVar from &quot;./contentScripts/getPageVar&quot;;
  import getPageVarFunc from &quot;./contentScripts/getPageVarFunc&quot;;
  import getAdsDotTxt from &quot;./contentScripts/adsDotTxtResponse&quot;;
  import $ from &quot;jquery&quot;;
  import Utils from &quot;./libs/utils.js&quot;;
  
  let adsDotTxtResponse = false;
  
  if (!adsDotTxtResponse) {
    console.log(&quot;No data&quot;);
    getAdsDotTxt();
    adsDotTxtResponse = true;
  }
  chrome.runtime.onMessage.addListener(function (
    { command, data },
    sender,
    sendResponse
  ) {
    try {
      switch (command) {
        case &quot;getPageVar&quot;:
          sendResponse({ success: true, data: getPageVar(data.pageVar) });
          break;
        case &quot;getPageVarFunc&quot;:
          sendResponse({ success: true, data: getPageVarFunc(data.pageVar) });
          break;
        case &quot;setPrebidHandlers&quot;:
          console.log(&quot;Case SetPrebidHandlers&quot;);
          console.log(prebidEventHandlersSet);
          if (!prebidEventHandlersSet) {
            setPrebidHandlers();
            prebidEventHandlersSet = true;
          }
          sendResponse({ success: true, data: &quot;Script executed&quot; });
          break;
        case &quot;getAdsDotTxt&quot;:
          console.log(&quot;send ads.txt response&quot;);
          if (!adsDotTxtResponse) {
            console.log(&quot;No data&quot;);
            getAdsDotTxt();
            adsDotTxtResponse = true;
            sendResponse({ success: true, data: &quot;Fetching ads.txt data&quot; });
          } else {
            console.log(&quot;Sending Data&quot;);
            sendResponse({
              success: true,
              data: getPageVarFunc(
                'document.getElementById(&quot;_My_adsDotTxt&quot;).innerText'
              ),
            });
          }
          break;
        case &quot;scrollAdToScreen&quot;:
          const status = Utils.scrollElementToScreen($(`div[id='${data.id}']`));
          sendResponse({ success: status, data: { status } });
          break;
        case &quot;highlightAds&quot;:
          Utils.borderifyAd(data.isMy);
          sendResponse({ success: true, data: { status: true } });
          break;
        case &quot;adUnitReporting&quot;:
          Utils.getAdUnitReporting(data.isMy, data.toDate, data.fromDate);
          sendResponse({ success: true, data: { status: true } });
          break;
        case &quot;appendAndReloadUrl&quot;:
          Utils.appendAndReloadURL(data.param);
          sendResponse({ success: true, data: { status: true } });
          break;
      }
    } catch (e) {}
    return true;
  });
  </code></pre>