0

My question is about the order (the sequence) that the script files run.

I call a script file named "aaa.js" and as callback of the executeScript I have the file script "bbb.js", like shown is the following sketch code:

chrome.tabs.executeScript(tabid, {file:"aaa.js", runAt: 'document_start' },
  function() {
    chrome.tabs.executeScript(tabid, {file:"bbb.js", runAt: 'document_start' });
  }
);

Theoretically, the "bbb.js" file executes only after the "aaa.js" finishes.

Since the "aaa.js" uses several instances of image.onload = function(){...}, and the management of the onload event handler is asynchronous, my question is:

Are all tasks (that are been put in queue, related with to asynchronous behavior of the "aaa.js") fully concluded, before the execution of the "bbb.js"?

1 Answer 1

1

No, there is no guarantee of that. The thread that injection of "aaa.js" starts terminates before async tasks complete, so I expect "bbb.js" to be injected as soon as that happens.

To achieve what you want, you need to determine the moment that all of your async tasks terminate, and then request the next injection with sendMessage, as a possible mechanism.


As per request, providing one possible way of doing so, using native JavaScript Promises:

  1. Wrap onload in a Promise object:

    function onloadPromise(img, src, handler){
      return new Promise(function (resolve, reject){
        img.addEventListener('load', function(){
          resolve( handler(img) ); // Resolve promise with result of the function
        });
        img.addEventListener('error', function(){ 
          reject( Error("Image " + src + " could not be loaded") ); 
        });
    
        img.src = src;
      });
    }
    
  2. Define handlers:

    function onloadHandler(img){
      console.log("Done: " + img.src);
      /* Your handler code */
    }
    
    function handleError(err){
      console.error(err);
    }
    
    function requestNextInject(){
      console.log("All done");
      chrome.runtime.sendMessage({"onloadDone": true});
    }
    
  3. Assuming arrays images and sources, make an array of promises:

    var promises = [];
    for(var i in images){
      promises.push(onloadPromise(images[i], sources[i], onloadHandler));
    }
    

    Change this logic as you see fit, the important part is to construct an array of onloadPromise(img, src, handler) for all of your images.

  4. Chain it all together:

    Promise.all(promises).then(requestNextInject).catch(handleError);
    

    This will wait until all Promises resolve before executing requestNextInject, or call handleError if any of the images fails to load. And by "wait" I mean "add an async task that will only execute after promises".

  5. In the background script, inject the second script:

    chrome.runtime.onMessage.addListener(
      function(request, sender, sendResponse){
        if(request.onloadDone) {
          chrome.tabs.executeScript(
            sender.tab.tabId,
            {file: "bbb.js"}
          );
        }
      }
    );
    
Sign up to request clarification or add additional context in comments.

2 Comments

How to do it, in this case ??
@user3059287 Edited to include one possible implementation. Async stuff is tricky; Promises are but one way to deal with it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.