DISQUS

Perplexed Labs: PHP jQuery AJAX Javascript Long Polling

  • Rowan · 7 months ago
    Hello. This is the best source of info I have found on this technique using jQuery, but I have a quick question. what would be a good example to use for $data = $datasource->getLatest();

    currently when i make getLast() output anything, it will just make the loop go extremely fast and output all the data, even if I make it statically output the number 4, it will still loop it, even though the data is the same... does this make sense?
  • Matt · 7 months ago
    @Rowan

    The purpose of that line of code would be where you would check a datasource (memcache, mysql db, etc.) for new data. In a chat application your app will receive events from chat clients (new msgs, status updates, etc.). You would need to do some logic in this method to check to make sure you aren't sending the same data over and over again.

    You only want to output something (and break execution of the "infinite" loop) if theres something that NEEDS to be output. Notice the "break;" within the if. Essentially its only going to echo output and break the loop if the data returned from the getLatest() call isn't empty (as in, "we have new events").

    I think the reason why your loop is going really fast is exactly because you're returning a constant like the number 4, which ISNT empty. The loop echo's, break's and jQuery restarts it.

    Does this help?
  • John · 7 months ago
    Looks promising, is it possible to expand this out a bit? Perhaps offer some demos/examples? I'm trying to learn long polling, and I reckon this would help me crack it.
  • matticakes · 7 months ago
    John,

    Are you having trouble tailoring the example code I provided to your domain? What are you trying to accomplish?
  • adrien · 6 months ago
    Interesting but what happen if you implement this technique on a page that have other AJAX features ?

    ajax requests will be queued until no response received from lpStart :x
  • adrien · 6 months ago
    mmmh that's maybe why sub-domain is a good idea, I'll try =)
  • Way · 6 months ago
    I'm working for a couple of weeks with that kind of ajax techniques. At the moment I'm standing before a big problem. Let me explain:
    As in this implementation above I use an while-loop on server side. Before i start this while, I start the session and check, if the current user is logged in.
    So here is my problem. I find out that the session is the reason for my problem. Cause if I break the client request via hitting F5 to refresh the page and my script loads again, it have to wait until the server leaves the while-loop.
    For example, i poll the server and my while looks exactly like that above and runs 30 seconds.
    If I refresh my page and make a new request to server after 5 seconds, my client has to wait for the rest of 25 seconds until the server recognize the new request and starts the while again.

    This is quite not that what I want. Have anyone an idea or solution?
    I've tried things like "ignore_user_abort(false)" but that's not the answer of my problem.

    btw. I'm from Germany so sorry for my very own version of English ;)
  • matticakes · 6 months ago
    Way,

    I believe this has to do with PHP Sessions using the default "files" save_handler. In order to prevent race conditions with data inside the $_SESSION variable PHP locks the file its storing the data in. A second request that tries to initiate a session tries to access this same file and waits for it to become available.

    If you use a custom session save_handler (like memcache or your database) and implement variable level locking (instead of session level locking) you can circumvent this problem.

    Perhaps this is a good blog post, I'll write something up.

    Thanks,

    -Matt
  • Way · 6 months ago
    Thank you very much Matt,

    I've suspected that. Actually I try to work with comet and an iframe-technique. But i think there is that problem too. So I will definitely need a custom session handler.
  • Az · 5 months ago
    Try session_write_close(); I wasted 2 weeks of my life to get rid of it, But session_write_close() helped me. Problem was exactly the same.
  • Marko Jovanovic · 3 months ago
    Thank you... Thank you...Hey did i say THANK YOU!
    You probably saved 2 weeks of my life :)
  • Dave · 6 months ago
    Thanks for writing this, it's pretty much what I'll be working on over the next few weeks. One question I have though is we're running Apache 2.2.11 and PHP 5.2.9 on a cPanel box. I don't want to switch to another web server if I can help it, though cPanel does allow you to install FastCGI. Initially HTTP requests to/from the server will be low, but we have a fast enough box to support the load. Would FastCGI help us out in this instance?

    Thanks in advance,

    Dave
  • matticakes · 6 months ago
    Dave,

    No, using FastCGI as an interface for PHP and Apache wouldn't help. It's Apache itself thats the problem. It isn't a web server meant for a high-volume of simultaneously open connections.

    It isn't that difficult to get up and running with lighttpd on a cPanel box.

    -Matt
  • Dave · 6 months ago
    What about LiteSpeed with FastCGI support? Any known issues with that or does it fall under the same category as Lighttpd and nginx?

    Thanks,

    Dave
  • matticakes · 6 months ago
    Dave,

    I think you're thinking about this wrong. You don't need FastCGI in order to scale an app that uses this technique. FastCGI just happens to be a common interface of servers that are able to scale with an app using this technique.

    Lighttpd would be my suggested choice given that it's easy to get PHP up and running on it and is fairly easy to install.

    -Matt
  • Dave · 6 months ago
    OK, thanks Matt, much appreciated.
  • d1Mm · 3 months ago
    > sleep(25000);
    it's about 7 hours ;)
    may be usleep(25000) ?
  • imwoodie · 3 months ago
    Hi, I'm using jquery-1.3.2.. I try to implement your code and is running well in FF, safari, and opera. but it doesn't work in IE.. would you like to give me a clue.. thank you
  • matticakes · 3 months ago
    have you tried enabling script debugging to see what line of code is causing the problem?
  • imwoodie · 3 months ago
    thanks for reply matt.. appreciate.

    well there's no error code in I.E, I'm not using jason but xml as a data..
    here are code that I try to implement :


    <script src="jquery-1.3.2.min.js" type="text/javascript"></script>
    <script type="text/javascript">
    var lpOnComplete = function(response) {
    $(response).find('id').each(function(){
    var id = $(this);
    bidid = id.attr("id");
    alert('bidid');
    // do more processing
    });

    lpStart();
    };

    var lpStart = function() {
    //$.ajaxSetup({ cache: false });
    $.get('proc.php', { }, lpOnComplete, 'XML');
    };

    $(document).ready(lpStart);
    </script>


    This is proc.php, I'm using memcache


    <?php
    $time = time();
    while((time() - $time) < 30) {

    // query memcache, database, etc. for new data
    $memcache_obj = memcache_connect('127.0.0.1', 11211);
    $data = "<?xml version='1.0' encoding='iso-8859-1'?>
    <data>" . memcache_get($memcache_obj, 'bid') . "</data>";

    // data is always new
    if(!empty($data)) {
    Header("Content-Type: text/xml");
    echo $data;
    break;
    }
    usleep(2500);
    flush();
    }
    ?>


    It doesn't work in I.E

    Thanks again matt
  • matticakes · 3 months ago
    A couple things.

    You should move your memcache connection line outside the while loop - you don't want to reconnect every iteration.

    $data, the way you have it written, can never be empty so the loop will always only run one iteration.

    If there are no script errors being reported, is an empty alert box being displayed?
  • imwoodie · 3 months ago
    thanks for correction in memcache matt, great..

    sorry, the code above was alert(bidid) not alert('bidid');
    the alert box is displayed well with returned data from xml
    it works in all browser except in I.E all version
    in I.E the alert box is not displayed.. that's the problem

    Well anyway I just have find the way to make it works in IE
    I changes the lpStart function as follow:


    var lpStart = function() {
    $.ajax({
    type: "POST",
    cache: false,
    url: "proc.php",
    success: lpOnComplete
    });
    };


    as u suggest for the memcache in proc.php i put this following code..

    <?php
    $memcache_obj = memcache_connect('127.0.0.1', 11211);
    $time = time();
    while((time() - $time) < 30) {

    // query memcache, database, etc. for new data
    $data = "<?xml version='1.0' encoding='iso-8859-1'?>
    <data>" . memcache_get($memcache_obj, 'bid') . "</data>";

    // data is always new
    if(!empty($data)){
    Header("Content-Type: text/xml");
    flush();
    usleep(1000000);
    echo $data;
    break;
    }
    }
    ?>


    it's using 2 thread on apache with keep alive connection, better than using setTimeout or setInterval, which use 60 thread for every second retrieving new data.

    I hope it help the other who get the problem in IE.. this browser always make me work twice..
    Thank you matt.. much appreciated.
  • TJ Mapes · 1 week ago
    Wow great post, does this FB Work?