title: Multiple chrome.runtime.onMessage-Listeners - disconnected port error
body: <p>I´m working on a chrome-extension which uses the indexedDB-Wrapper <a href="https://github.com/dfahlander/Dexie.js/wiki/Dexie" rel="noreferrer">Dexie</a>, several jQuery-Libraries and <a href="https://www.syncfusion.com/products/javascript" rel="noreferrer">syncfusions eGrid</a> to display and modify the database. I know this question was asked several times before, but now I discovered some weird behaviour.</p>
  
  <p>My Setup:</p>
  
  <ul>
  <li>background-script </li>
  <li>content-script (injected into a website) </li>
  <li>index.html (for displaying the Grid) </li>
  <li>manifest.json</li>
  </ul>
  
  <p>When I´m reloading my extension everything is fine. I´m injecting a scrollable list of names with my content-script. This also works when I´m reloading the tab. But when I opened the index.html before <s>(popup.html in the official documentation)</s> the sendResponse from background-script stops working after some time. Reloading the tab would not help then. I was searching for hours, found a lot of similiar cases and some entrys on googles bugtracker where they claimed this problem was already fixed. I also know that I have to use return true if I have async funtions like with indexedDB.</p>
  
  <p>So to give you some more information, I will list my shortened scripts.</p>
  
  <p><strong>Content-Script</strong></p>
  
  <pre class="lang-js prettyprint-override"><code>chrome.runtime.sendMessage({greeting: 'getNames'},function(response){
      $('.names-container').append(response.farewell);
  });
  chrome.runtime.sendMessage({greeting: 'getData'+name},function(name){
      chrome.runtime.sendMessage({greeting: 'delete'},function(response){
          console.log(response.farewell);
      });
      chrome.runtime.sendMessage({greeting: 'set'}, function(response) {
          console.log(response.farewell);
      });
  });
  </code></pre>
  
  <p><strong>Background-Script</strong></p>
  
  <pre class="lang-js prettyprint-override"><code>chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){
    if(message.greeting == 'getNames'){
      // Get array of names from idb and send it back
      idb.opendb().then(function(a){
        sendResponse(a);
      });
      return true;
    } else if(message.greeting.indexOf('getData') &gt;= 0){
      // get more information for selected name
      idb.opendb().then(function(a){
        sendResponse(a);
      });
      return true;
    } else if(message.greeting == 'delete'){
      // further processing to delete some stuff
      idb.opendb().then(function(a){
        sendResponse(a);
      });
      return true;
    } else if(message.greeting == 'set'){
      // synchronous function
      // do something ...
      return false;
    } else {
      // Do something
    }
    //return true;
  });
  
  funtion indexhtml(){
    chrome.runtime.sendMessage(
      "notifications",
      function (response) {
        console.log(response);
      }
    );
  }
  </code></pre>
  
  <p><strong>Index.html</strong></p>
  
  <pre class="lang-js prettyprint-override"><code>chrome.runtime.onMessage.addListener(function(request, sender, sendResponse){
    if(request == 'notifications'){
      notifications();
    }
  
    sendResponse("Message received from background-page for "+request);
  });
  </code></pre>
  
  <p><strong>Manifest</strong></p>
  
  <pre class="lang-json prettyprint-override"><code>{
      "manifest_version": 2,
      "name": "MyExtension",
      "description": "Some desc...",
      "version": "0.2",
      "background": {
          "scripts": ["js/jquery-2.1.4.min.js", "js/background.js", "...",
          "persistent": true
      },
      "default_locale": "en",
      "content_scripts": [
          {
              "matches": ["&lt;all_urls&gt;"],
              "js": ["js/jquery-2.1.4.min.js"]
          },
          {
            "matches": ["https://domain.tld/*"],
            "js": ["js/jquery-2.1.4.min.js", "js/contentscript.js"],
            "css" : ["css/contentscript.css",
            "run_at": "document_start"
          }
      ],
  
      "icons": {
          "16": "images/icon-16x16.png",
          "48": "images/icon-48x48.png",
          "128": "images/icon-128x128.png"
      },
      "browser_action": {
          "default_icon": "images/icon-128x128.png"
      },
      "permissions": [
          "cookies", "tabs", "alarms", "webRequest", "webRequestBlocking", 
          "contextMenus", "&lt;all_urls&gt;", "storage"
      ],
  
      "content_security_policy": "script-src 'self' 'unsafe-eval'; 
      object-src 'self'"
  }
  </code></pre>
  
  <p>It is difficult for me to debug this behaviour, since I can´t exactly know when the Error <code>Attempting to use a disconnected port object</code> appears. It looks like the port doesn´t gets closed correctly after the sendResponse is executed and only if the index.html was opened.</p>
  
  <p>Finally the shortened Error-Message:</p>
  
  <pre><code>Error: Attempting to use a disconnected port object
      at Error (native)
      at PortImpl.postMessage (extensions::messaging:65:22)
      at Port.publicClass.(anonymous function) [as postMessage] (extensions::utils:94:26)
      at responseCallback (extensions::messaging:163:16)
  </code></pre>
  
  <p>The idb-Functions are customized and won´t work like I wrote them here, but I just want to show what I´m doing there. I´m using <code>.then()</code> to <code>sendReponse</code> when the result is available and <code>return true;</code> to wait for the result if async. I also searched every script for <code>onMessage</code> and <code>sendMessage</code>. The listed functions related to onMessage/sendMessage are all that I´m using, they are not used elsewhere. I´m using a timer for <code>indexhtml()</code> to save an array containing the notifications in a specified interval and then executing a function at index.html to reload the notifications.</p>
  
  <p>The index.html Tab gets opened via browserAction:</p>
  
  <pre class="lang-js prettyprint-override"><code>chrome.browserAction.onClicked.addListener(function(tab){
      chrome.tabs.create({url: chrome.extension.getURL('index.html')});
  });
  </code></pre>