Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 7 of 7
  1. #1
    New to the CF scene
    Join Date
    Jun 2013
    Posts
    4
    Thanks
    1
    Thanked 0 Times in 0 Posts

    Ajax slow with asynchronous callbacks.

    Greetings to everyone, I'm new here and hope I'll learn much from you folks :-)
    First if all, I'm new to web development and I'm doing some project which is AJAX based, but I've got a little problems here..
    Whenever I'm trying to do something with asynchronous callbacks, it gets slow, but without it, it works fine. Server responds normally when using synchronous callbacks. The data is max 10 bytes long when receiving (not including HTTP headers), but doing like 20 requests per second. Project itself is simple, it must check the value returned by PHP script and set button name & background color with returned values. Here's simple code that demonstrates it.

    js/ajax.js
    Code:
    window.setInterval(status_loop, 1000);
    
    function ajax_callback(xmlhttp, args) {
    
        // response will be something like 123:#FFFFFFFF
        var status = xmlhttp.responseText.split(':');
        document.getElementById(args).innerHTML = status[0];
        document.getElementById(args).style.background = status[1];
    }
    
    function new_xmlhttp(callback, args) {
        
        var xmlhttp;
        if(window.XMLHttpRequest) {
            xmlhttp = new XMLHttpRequest();
        } else {
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        
        return xmlhttp;
    }
    
    function ajax_get(data, callback, args) {
        
        var xmlhttp = new_xmlhttp();
        
        xmlhttp.onreadystatechange = function() {
            if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
                // OK.
                callback(xmlhttp, args);
            }
        }
        
        xmlhttp.open("GET", "functions.php?" + data, true);
        xmlhttp.send(null);
    }
    
    function get_status(objId) {
        
        ajax_get("status=" + objId, ajax_callback, objId);
    }
    
    function status_loop() {
    
        get_status(1);
        get_status(2);
        ...
    }
    index.html
    Code:
    <button type="button" id=1 onClick="get_status(1)">Button 1</button>
    <button type="button" id=2 onClick="get_status(2)">Button 2</button>
    ... more buttons
    with asynchronous calls, it takes 2-3 or even 4 seconds to finish but without it, it takes 10 to 20 ms.. What I'm doing wrong?

    Regards.

  • #2
    Senior Coder
    Join Date
    Dec 2010
    Posts
    2,396
    Thanks
    12
    Thanked 569 Times in 562 Posts
    With your code you are starting all of the initial requests (get_status(1), get_status(2), ... etc) at the same time, which is not a good idea to say the least. Browsers do not support more than a few requests at the same time. That might be the reason why it slows down

    You should serialize your requests by starting the next request only after the previous one finished.

  • #3
    New to the CF scene
    Join Date
    Jun 2013
    Posts
    4
    Thanks
    1
    Thanked 0 Times in 0 Posts
    By the way, without setInterval function, it has the same problem. I mean, with asynchronous calls (using 1 request only) it takes 2-3 seconds to finish and without it, it takes 10 or 20 ms. What's the real problem?

    Regards.

  • #4
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,298
    Thanks
    10
    Thanked 584 Times in 565 Posts
    show us the code without asynchronous calls, the one that's fast, so we can see what changes between them.
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%

  • #5
    New to the CF scene
    Join Date
    Jun 2013
    Posts
    4
    Thanks
    1
    Thanked 0 Times in 0 Posts
    Here's the synchronous version of it.
    Code:
    function new_xmlhttp() {
        var xmlhttp;
        if(window.XMLHttpRequest) {
            xmlhttp = new XMLHttpRequest();
        } else {
            xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
        
        return xmlhttp;
    }
    
    function ajax_get(data) {
        var xmlhttp = new_xmlhttp();
        
        xmlhttp.open("GET", "functions.php?" + data, false);
        xmlhttp.send(null);
        
        return xmlhttp.responseText;
    }
    
    function get_status(objId) {
        var status = ajax_get("status=" + objId).split('|');
        if(status) {
            document.getElementById(objId).innerHTML = status[0];
            document.getElementById(objId).style.background = status[1];
        }
    }

  • #6
    Senior Coder rnd me's Avatar
    Join Date
    Jun 2007
    Location
    Urbana
    Posts
    4,298
    Thanks
    10
    Thanked 584 Times in 565 Posts
    the reason the sync version works is because your php file takes longer than 1/20th of a second to round-trip to the browser.

    sync cannot get backed up since it only grabs one at a time; it forces your app to wait. if you track the updates in the console, you should be able to observe it getting behind where it's supposed to be after a little bit. if it should be going 10X a second, console.log(+new Date), and see if the numbers are actually 100 apart; they likely won't be.

    since the async version doesn't wait for a return, it DOES get backed up easily. once you open a few connections, other connections slow down, and the problem quickly spirals to the point where there are so many open and waiting to be opened connections that nothing gets done.

    all you need to do it switch the async routine to run like your sync: only fire the next fetch when the current one is complete (plus a small delay if you want).


    that means, kill this line:

    Code:
    window.setInterval(status_loop, 1000);
    add this line:

    Code:
    window.setTimeout(status_loop, 1000);

    and call next on complete:
    Code:
    function ajax_callback(xmlhttp, args) {
    
        // response will be something like 123:#FFFFFFFF
        var status = xmlhttp.responseText.split(':');
        document.getElementById(args).innerHTML = status[0];
        document.getElementById(args).style.background = status[1];
        setTimeout(status_loop, 800)
    }
    my site (updated 13/9/26)
    BROWSER STATS [% share] (2014/5/28) IE7:0.1, IE8:5.3, IE11:8.4, IE9:3.2, IE10:3.2, FF:18.2, CH:46, SF:7.9, NON-MOUSE:32%

  • Users who have thanked rnd me for this post:

    warlockn (06-03-2013)

  • #7
    New to the CF scene
    Join Date
    Jun 2013
    Posts
    4
    Thanks
    1
    Thanked 0 Times in 0 Posts
    Thanks, will try it :-)


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •