Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would I design a client-side Queue system?

OVERVIEW

I'm working on a project and I've come across a bit of a problem in that things aren't happening in the order I want them to happen. So I have been thinking about designing some kind of Queue that I can use to organize function calls and other miscellaneous JavaScript/jQuery instructions used during start-up, i.e., while the page is loading. What I'm looking for doesn't necessarily need to be a Queue data structure but some system that will ensure that things execute in the order I specify and only when the previous task has been completed can the new task begin.

I've briefly looked at the jQuery Queue and the AjaxQueue but I really have no idea how they work yet so I'm not sure if that is the approach I want to take... but I'll keep reading more about these tools.

SPECIFICS

Currently, I have set things up so that some work happens inside $(document).ready(function() {...}); and other work happens inside $(window).load(function() {...});. For example,

<head>
  <script type="text/javascript">    

    // I want this to happen 1st
    $().LoadJavaScript();
    // ... do some basic configuration for the stuff that needs to happen later...

    // I want this to happen 2nd
    $(document).ready(function() {

      // ... do some work that depends on the previous work do have been completed
      var script = document.createElement("script");
      // ... do some more work...
    });

    // I want this to happen 3rd
    $(window).load(function() {

      // ... do some work that depends on the previous work do have been completed
      $().InitializeSymbols();
      $().InitializeBlock();
      // ... other work ... etc...
    });
  </script>
</head>

... and this is really tedious and ugly, not to mention bad design. So instead of dealing with that mess, I want to design a pretty versatile system so that I can, for example, enqueue $().LoadJavaScript();, then var script = document.createElement("script");, then $().InitializeSymbols();, then $().InitializeBlock();, etc... and then the Queue would execute the function calls and instructions such that after one instruction is finished executing, the other can start, until the Queue is empty instead of me calling dequeue repeatedly.

The reasoning behind this is that some work needs to happen, like configuration and initialization, before other work can begin because of the dependency on the configuration and initialization steps to have completed. If this doesn't sound like a good solution, please let me know :)

SOME BASIC WORK

I've written some code for a basic Queue, which can be found here, but I'm looking to expand its functionality so that I can store various types of "Objects", such as individual JavaScript/jQuery instructions and function calls, essentially pieces of code that I want to execute.

UPDATE

With the current Queue that I've implemented, it looks like I can store functions and execute them later, for example:

// a JS file... 
$.fn.LoadJavaScript = function() {

    $.getScript("js/Symbols/Symbol.js");
    $.getScript("js/Structures/Structure.js");
};

// another JS file...
function init() { // symbols and structures };

// index.html
var theQueue = new Queue();
theQueue.enqueue($().LoadJavaScript);
theQueue.enqueue(init);

var LJS = theQueue.dequeue();
var INIT = theQueue.dequeue();

LJS();
INIT();

I also think I've figured out how to store individual instructions, such as $('#equation').html(""); or perhaps even if-else statements or loops, by wrapping them as such:

theQueue.enqueue(function() { $('#equation').html(""); // other instructions, etc... });

But this approach would require me to wait until the Queue is done with its work before I can continue doing my work. This seems like an incorrect design. Is there a more clever approach to this? Also, how can I know that a certain function has completed executing so that the Queue can know to move on? Is there some kind of return value that I can wait for or a callback function that I can specify to each task in the Queue?

WRAP-UP

Since I'm doing everything client-side and I can't have the Queue do its own thing independently (according to an answer below), is there a more clever solution than me just waiting for the Queue to finish its work?

Since this is more of a design question than a specific code question, I'm looking for suggestions on an approach to solving my problem, advice on how I should design this system, but I definitely welcome, and would love to see, code to back up the suggestions :) I also welcome any criticism regarding the Queue.js file I've linked to above and/or my description of my problem and the approach I'm planning to take to resolve it.

Thanks, Hristo

like image 337
Hristo Avatar asked Jan 12 '11 07:01

Hristo


2 Answers

I would suggest using http://headjs.com/ It allows you to load js files in parallel, but execute them sequentially, essentially the same thing you want to do. It's pretty small, and you could always use it for inspiration.

I would also mention that handlers that rely on execution order are not good design. I am always able to place all my bootstrap code in the ready event handler. There are cases where you'd need to use the load handler if you need access to images, but it hasn't been very often for me.

like image 127
Juan Mendes Avatar answered Nov 08 '22 10:11

Juan Mendes


Here is something that might work, is this what you're after?

var q = (function(){
    var queue = [];
    var enqueue = function(fnc){
        if(typeof fnc === "function"){
            queue.push(fnc);
        }
    };

    var executeAll = function(){
        var someVariable = "Inside the Queue";
        while(queue.length>0){
            queue.shift()();
        }
    };

    return {
        enqueue:enqueue,
        executeAll:executeAll 
    };

}());

var someVariable = "Outside!"
q.enqueue(function(){alert("hi");});
q.enqueue(function(){alert(someVariable);});
q.enqueue(function(){alert("bye");});
alert("test");
q.executeAll();

the alert("test"); runs before anything you've put in the queue.

like image 21
david Avatar answered Nov 08 '22 10:11

david