1

I have 2 ajax calls (one to fetch header content & one to fetch images content). Both are returned in JSON format. To render, I have 2 handlebar templates.

Issue is: only one of the handlebars template is being rendered (sometimes header gets rendered & sometimes images get rendered). URL: http://www.devfolio.info/ankit/index.php

CODE: JS File

function getPhotos(uid){
    var dataString = 'action=viewPhotobank&uid=' + uid;
    $.ajax({
        type:"POST",
        url: "/themesAssets/controller/actions.php",
        data: dataString,
        success: function(msg){
            response = JSON.parse(msg);
            if(response.statusPhotos == "success"){
                if(typeof(afterGetUserphotobank) != 'undefined'){
                    afterGetUserphotobank();
                } else{
                    var sourcePhotos   = $("#images-template").html();
                    var templatePhotos = Handlebars.compile(sourcePhotos);
                    $("#content").fadeOut(animationTime, function(){
                        $("#content").html(templatePhotos(response))
                        .fadeIn(animationTime);
                    });
                }
            }
        }
    });
}

function getHeaderData(uid){
    var dataString = 'action=getHeader&uid=' + uid;
    $.ajax({
        type:"POST",
        url: "/themesAssets/controller/actions.php",
        data: dataString,
        success: function(msg){
            response = JSON.parse(msg);
            if(response.statusHeader == "success"){
                if(typeof(afterGetSingleImage) != 'undefined'){
                    afterGetHeaderData();
                } else{
                    var sourceHeader   = $("#header-template").html();
                    var templateHeader = Handlebars.compile(sourceHeader);
                    $("#header").fadeOut(animationTime, function(){
                        $("#header").html(templateHeader(response))
                        .fadeIn(animationTime);
                    });
                }
            }
        }
    });
}

ON THE MAIN PAGE:

<body>
        <div id="header"></div>
        <div id="content"></div>
        <div id="footer"></div>
        <script>
            $(document).ready(function(){
                getHeaderData(<?= $uid ?>);
                getPhotos(<?=$uid?>);
            });
        </script>
        <?php
        require_once $rootFolder . '/themes/classy/headerTemplate.php';
        require_once $rootFolder . '/themes/classy/imagesTemplate.php';
        ?>
</body>


<?php
require_once '../../global.php';
require_once $rootFolder . '/classes/portfoliodata.class.php';
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <?php
        $data = new portfolioData();
        $data->getViewport();
        $data->getCharset();
        $data->getCommonCSS();
        $data->getCommonJS();
        $data->getThemeCSS("classy", "grid");
        ?>
    </head>
    <body>
        <div id="header"></div>
        <div id="content"></div>
        <div id="footer"></div>
        <?php
        require_once $rootFolder . '/themes/classy/headerTemplate.php';
        require_once $rootFolder . '/themes/classy/singleImageTemplate.php';
        require_once $rootFolder . '/themes/classy/imagesTemplate.php';
        ?>
        <script>
            $(document).ready(function(){
                getHeaderData(<?= $uid ?>);
                getPhotos(<?= $uid ?>);
            });
        </script>
    </body>
</html>
Ankit
  • 137
  • 2
  • 10
  • You need to post code, show us what you've tried, what's failing specifically, etc. Possibly make a JSFiddle to demonstrate visually for us that we can edit. – Deryck Jan 11 '14 at 07:34
  • Similar issue (answer is broad but explains why this is happening better than I can) http://stackoverflow.com/questions/19084299/strange-behavior-with-multiple-ajax-requests-to-the-same-url – Deryck Jan 11 '14 at 10:24
  • Another related situation, this one describes how PHP and HTTP/1.1 are behind it. http://stackoverflow.com/questions/898190/jquery-making-simultaneous-ajax-requests-is-it-possible – Deryck Jan 11 '14 at 10:28

1 Answers1

0

~~~~~~EDIT~~~~~~

It's using the same cached response from whichever AJAX call wins the race.

Put this in your $.ajax(); calls (all of them) just before data:

cache: false,

If this doesn't get you a quick fix, then I'm going to sleep. Forever.

This doesn't get you off the hook from joining all these into one call. Just wanted you to understand the cause of the issue to learn from. In fact, this code needs a slight makeover, some aggregation and definitely popstates.

If Handlebars doesn't end up your cup of tea, I strongly suggest Angular.js. Same idea essentially but integrates directly into HTML as elements, attributes, etc.


Those AJAX calls are asynchronous - they don't care when the other one loads, they just load whenever they load.

You can prevent this by either:

responding with both things in one AJAX call (logically) and displaying the result using success: function() {

or

you can embed one call inside of the other's success: in the order you want them loading.

I do not recommend the second option.

Deryck
  • 7,608
  • 2
  • 24
  • 43
  • Yes so these AJAX calls are async, so why does it render only one template at a time ? I have 2 different JSONs being returned, two different templates, all variable names different (just to be double sure), so why is it that only one of the handlebars template is rendered & other isnt ? Live demo : http://www.devfolio.info/ankit/index.php – Ankit Jan 11 '14 at 07:46
  • Can you post the corresponding PHP to show what response is being sent and how – Deryck Jan 11 '14 at 07:51
  • Here's the JSON being returned, I got this from firebug: `{"statusHeader":"success","messageHeader":{"userConfig":{"footer":"Copyright @ Ankit Mahanot","title":"Ankit Mahanot Portfolio","titleAsLogo":"yes"},"userLogo":{"logoPath":"datastore\/ankit\/logo\/logo.jpg"},"userPages":[{"id":32,"title":"Another page ok?","content":"

    0<\/p>","publish":1,"pos":0},{"id":36,"title":"new page","content":"0","publish":0,"pos":0}],"layout":[{"theme":"grid"}]}}`

    – Ankit Jan 11 '14 at 07:54
  • the second JSON is big, but here's a piece of it : `{"statusPhotos":"success","messagePhotos":[{"id":553,"fileName":"Lion_image_11_1380737515.jpg","geotag":"","pictitle":"Lion","picdesc":"The lion is one of the four big cats in the genus Panthera and a member of the family Felidae. With some males exceeding 250 kg in weight, it is the second-largest living cat after the tiger.","picidea":"","catid":0,"pos":2,"featured":1}` – Ankit Jan 11 '14 at 07:56
  • I should be able to work with the JSON but that second one is truncated. Can you go to http://jsonmate.com/ and paste it and post the permalink here – Deryck Jan 11 '14 at 08:03
  • Try using a `sleep(2);ob_flush();flush();` at the end of the response function in PHP just to troubleshoot and see if it shows the header then photos after 2 seconds. I'm not too sure this will help but without your code I'm sorta shooting blind with sound. I really hope this works though because it will prove a theory of mine and the solution will be much easier. Oh and if you combine the AJAX calls into one (original answer I posted), I guarantee this issue will cease immediately. – Deryck Jan 11 '14 at 08:24
  • yes one ajax call would really solve the issue, I'm also thinking on those lines ... i'll give sleep(2) a try ... – Ankit Jan 11 '14 at 08:46
  • sleep(2) does the trick :-/ But why ?? can we not render 2 handlebars template in parallel ?? – Ankit Jan 11 '14 at 08:49
  • I think by calling them at the same time, one of them is beating the other and blocking it from posting its data. So both calls think they're waiting for a reply but one gets left at the alter with a postcard saying "JSON is with me now, nice try though". At least this is what I'm picturing in my head. – Deryck Jan 11 '14 at 09:01
  • By using `sleep(2)` you're preventing that second HTTP request from being processed by PHP, allowing it time to complete the first request before getting interrupted. `sleep()` is a blocking function that stops future requests from being executed until the timer finishes – Deryck Jan 11 '14 at 09:05
  • But the JSON is also different .. there's no common thing ... each call has it's own JSON, it's own backend method, it's one AJAX call method (as posted above) .. this is very weird :-/ encountered it for the first time – Ankit Jan 11 '14 at 09:05
  • Oh well then ignore everything I just said it's a Javascript rendering issue then. One sec lemme take another look. When you posted that JSON I was in the mindset of it being diagnostic - like you got it from feeding the server and receiving data manually. lol ive been up too long – Deryck Jan 11 '14 at 09:07
  • Can you post the rest of the HTML + Javascript as-is to a JSFiddle or JSbin - there's a ton of missing pieces that I passed off as unimportant earlier but one of those things might be getting overwritten or called twice or not at all, etc. – Deryck Jan 11 '14 at 09:11
  • http://www.devfolio.info/ankit/index.php - you can look at this page ... everything is there on this ... the json, template, html, javascript calls – Ankit Jan 11 '14 at 09:13
  • oh yeah. i knew that. – Deryck Jan 11 '14 at 09:17
  • Re-arrange where your Javascript loads. Put them at the end after `

    `. Are the three templates I see here (header, message, photo) generated by that PHP require_once or is it generated from your `Handlebars.compile()` in the AJAX?

    – Deryck Jan 11 '14 at 09:58
  • I updated my answer with what should be a sure fix for your problem. Let me know how it goes. – Deryck Jan 11 '14 at 10:41
  • cache: false didnt work :( and the templates are being put in using require_once in php. Added PHP code also to the question – Ankit Jan 11 '14 at 11:02
  • just started to write the code, definitely need a lot of changes, i will read more about angular js also ... can you elaborate more on "aggregation" aspect that you mentioned in your answer ? – Ankit Jan 11 '14 at 11:22
  • Connecting to a server to get a single file is like starting a car engine to move 10 yards and turning it off again, then repeating. Aggregation is just a fancy word for combining like-files (CSS, Javascript) into less files so the browser gets all the code with less trips to the server. Also usually a good idea to minify the JS and CSS so the file sizes shrink and interpretation is more efficient. – Deryck Jan 11 '14 at 12:59