Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

Execute set of Javascript method asynchronously

1.00/5 (1 vote)
12 Nov 2013CPOL3 min read 22.3K  

Objective 

Few days back I had a small requirement of running set of javascript method asynchronously. Kind of how ThreadPool works in C# or Java. So objective was to provide set methods with there required parameters and some jquery plug-in will take care of it's calling and finally after the execution callback method (provided during assignment) should fire back. 

Introduction 

Sometime it could be very useful, specially when you have set of javascript method, which can be fired and forget.

Background 

Implemented code is very simple and easy to follow. It will be nice if read has knowledge of javascript/jquery knowledge.

Using the code  

So to achieve this lets divide the whole objective into two parts. 

  • Jquery plug-in which will have gateway method to process user methods async.
  • Consume jquery plug-in and pass set of methods into that 

Lets see how jquery plug-in looks like:

JavaScript
jQuery.extend({
    JobPool: function (options, job, callback, data) {
        var obj = this;
        var options = $.extend({
        }, options);
        var joblist = Array();

        var QueueJob = function (job, callback, ops, data) {
            if (job == 'undefined') {
                return;
            }

            ops = ops || {};

            var jobItem = new JobItem(job, callback, ops, data);
            if (jobItem) {
                joblist.push(jobItem);

                QueueChanged.call();
            }
        };

        var JobItem = function (job, callback, ops, data) {
            var jobitem = this;
            ops = ops || {};
            this.Data = data;
            this.Job = job;
            this.Callback = callback;

            this.Run = function () {
                try {
                    if (!jobitem.Job) return;

                    var returnValue = jobitem.Job(jobitem.Data);

                    jobitem.Callback(returnValue);
                }
                catch (e) { }
            }
        }

        var AjaxCall = function (jobItem) {

            if (!jobItem) jobItem = this;

            $.ajax({
                url: "#",
                type: 'GET',
                dataType: 'html',
                async: true,
                timeout: 3000,
                cache: false,
                data: '',
                success: function (dt, x) {
                    //AddEntry("In call 1-" + data);
                    //alert('call go');
                    if (typeof(jobItem.Run) == 'function')
                        jobItem.Run.call();

                    QueueChanged.call();
                },
                error: function (obj, x) {
                    //AddEntry("In call 2-" + data);
                    //alert('call stop');
                    if (typeof(jobItem.Run) == 'function')
                        jobItem.Run.call();

                    QueueChanged.call();
                }
            });
        };

        var QueueChanged = function () {
            if (joblist == null || joblist.length == 0) return;

            var jobitem = joblist.pop();

            AjaxCall.call(jobitem);
        }

        QueueJob(job, callback, options, data);

        return this;
    }
});
AjaxCall is the helper method which actually simulate async nature. I am using $.ajax helper method to simulate async nature, because in javascript we don't have any API to support async nature. Thanks to HTML5, at least we have new Worker api. 

JobItem is the container which keep actual method to call and QueueJob is queuing the job to an array and since we have change in the array, so we are calling  QueueChanged api to process JobItem from updated Queue list.

Now lets see how we can consume it in our code.

JavaScript
 $(function () {
    for (i = 0; i < 10; i++) {
        //callAjax(i);
        $.JobPool({}, AddEntry, callbackItem, { 'value': "In call 1-"+i });
    }

    AddEntry("After Call");
});<span style="font-size: 14px;"</span>

Lets we are going to call some method when our document loaded. AddEntry is the method we are calling in Async way. Once AddEntry is processed we will be getting callback and our callbackItem method will be fired with return value. Last section of our JobPool method is the Json data which will be passed as input AddEntry method. 

Now lets follow our callback method. callbackItem method will be fired once AddEntry method finished it's job.  

JavaScript
 function callbackItem(obj) {
    AddEntry("got callback-");
}  

Lets see our sample AddEntry method, which should be replaced with your actual javascript method. 

JavaScript
function AddEntry(obj) {

    var strVal = '';

    if (typeof (obj) == 'object')
        strVal = obj.value;
    else
        strVal = obj;

    var el = document.createElement("div");
    $(el).text(strVal + " - " + new Date().getTime().toString());
    $('#container')[0].appendChild(el);
}

This AddEntry method is just sample method. In this place you can use any method which will be called in Async way. In your html page you should have one <div> whose id is container.

If you run the above example you will notice we are calling methods (AddEntry) in a sequential way, but when actual method is being called are not in sequence. If you keep on press F5 you will see different outcome time to time. So it will be unpredictable sometime when which method will be fired. Very similar to ThreadPool. 

Points of Interest 

We all know it's simple but in my opinion it's really fun. Though I drawn similarity with ThreadPool, but please don't read me wrong. ThreadPool is not this much simple. There are many improvement can be done in this code. Firstly try .. catch is not applied in all the places, which I should add. Secondly all the method is consider for action as soon as that method added to the list. It's not right thing. I should check how many operations alive and arrange next method call based on that. Otherwise if many javascript method is called at same time, UI thread will be blocked and user might be frustrated by seeing it.

I am sure missed lot of points here, so your suggestions are well accepted and lets learn together. Your suggestions will encourage me in writing more cool! stuffs.

That's all folks! 

<embed type="application/x-dap-background" id="DAPPlugin" style="visibility: collapse;" />

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)