Search code examples
javascriptasynchronousgoogle-chrome-extensionpromise

Chrome Extensions synchronous calls - create window only after window closed



I have this code:

function voteNewWindow(mailNum) {
    chrome.windows.create({
        url: 'http://www.google.com',
        incognito: true
    }, function (window) {
        console.log('created ' + window.id);
        chrome.tabs.query({
            active: true,
            windowId: window.id
        }, function (tabs) {
            var tab = tabs[0];
            chrome.tabs.executeScript(tab.id, {
                file: "jquery-2.1.1.min.js"
            }, function () {
                chrome.tabs.executeScript(tab.id, {
                    file: "content_script.js"
                }, function () {
                    chrome.tabs.sendMessage(tab.id, {
                        email: JSON.parse(localStorage.mailList)[mailNum]
                    }, function (response) {
                        console.log(response);
                        chrome.windows.remove(window.id);
                        console.log('window ' + window.id + " removed");
                    });
                });

            });
        });

    });
}


function execute() {

    for (var i = 0; i < JSON.parse(localStorage.mailList).length; i++) {

        voteNewWindow(i);
    }
}

The problem is that all windows open at the same time. I want a window to open only when the one before is closed. I want voteNewWindow() to finish all it has to do before another voteNewWindow() executes.
Any help would be appreciated. Thanks


Solution

  • JavaScript Promises to the rescue!

    function voteNewWindow(mailNum) {
      return function(){
        return new Promise( function (resolve, reject){
          chrome.windows.create({
          /* ... */
                            }, function (response) {
                                console.log(response);
                                chrome.windows.remove(response.id);
                                console.log('window ' + response.id + " removed");
                                resolve(); // Proceed to the next
                            });
          /* ... */
        }
      }
    }
    
    function execute() {
      var sequence = Promise.resolve();
      for (var i = 0; i < JSON.parse(localStorage.mailList).length; i++) {
        sequence = sequence.then(voteNewWindow(i));
      }
    }
    

    See this section to understand what's happening here. Basically, we're creating a chain of Promises glued together by then, which ensures the next one will start executing only after the previous one has finished.

    If you need to do any other action after execute(), put it at the end of the sequence:

    function execute(callback) {
      var sequence = Promise.resolve();
      for (var i = 0; i < JSON.parse(localStorage.mailList).length; i++) {
        sequence = sequence.then(voteNewWindow(i));
      }
      sequence.then(callback);
    }