Reputation: 1511
I should start by saying that I'm running my site from PHPStorm's inbuilt webserver, but I think the problem is in my method, not the environment.
I'm redesigning my outdated games website. I thought it would be a good idea to have my PHP dependant content load by AJAX instead of includes at the top of a page that can only be run once.
In this example, the page loads very quickly but there are 2 sections that have independent AJAX loaded content that take unusually long to load. The 3 blue lines inside the boxes animate to indiciate it is loading.
The relevant jquery and javascript stuff is in the html body, as the site uses a template (containing the header, footer and basically everything that is require for each page) and simply includes the unique page content in the middle, eg - include 'main.php'; index.php doesn't have a head or body, it just contains js and html. However, I wait until $(document).ready to run any javascript so I don't think this is important.
The first to load is the news section, because it is called first in the javascript. This simply grabs a single element from a mysql table. This alone takes upto 2 seconds.
Next is the last 3 tweets on my timeline, I run a very efficient, simplified Twitter timeline retrieving PHP script, this also takes around 2 seconds.
Also consider I've yet to implement a getGames.php for retrieving all the necessary game info from the database, the wide thumbnails are currently just placeholders, so in total my site will be taking even longer to load all of its content.
Anyway, I realised that if I just do include 'getTweets.php' and 'getNews.php', the raw content appears to load much much quicker, no ajax necessary. However the echoed data gets printed on the page.
The thing is, I'm likely never to call those AJAX function again on this particular page, so the reason for using AJAX on this page is simply consistency and thinking ahead, but there are other pages (the news section for instance) where I will have to use AJAX to get news articles via getNews.php. Obivously I don't want to have 2 files with almost the exact same PHP code, but I can't see any elegant solution for using both AJAX and includes. Perhaps I could have one great big ajax.php which can return all the necessary page data in a single call instead of calling AJAX multiple times with different PHPs? I don't know...
I'm sure there's nothing wrong with the php code itself (getting tweets or news from the database were coded with efficiency in mind), just my method. I wasn't going to include any code, I don't think it makes my problem any easier to understand, but anyway:
index.php, javascript section:
function ajax(page, inputData, outputHandler, errorHandler) {
$.ajax({
type: "POST",
url: page,
data: inputData,
success: function(data){
outputHandler(JSON.parse(data));
},
error:errorHandler
});
}
$(function() {
$("#tweet-container").append($.parseHTML(loadingIcon));
$("#news-container").append($.parseHTML(loadingIcon));
ajax("/ajax/getNews.php", { }, function(data) {
$("#news-container").empty();
for (var i = 0; i < data.length; i++) {
var date = data[i].dateadded;
date = $.timeago(date);
var text = data[i].news;
text = text.replace(/<br\s*[\/]?>/gi, "\n");
text = $.trim($(text).text());
//'+ data[i].author+'
text = '<img src="/images/Frosty.png" alt="%s" align="left" style="padding:6px 5px; background:pink; margin-right:5px;"/>' + text;
var title = data[i].title;
var newsData = { header: date, title:title, content:text };
var article = Mustache.render(newsTemplate, newsData);
$("#news-container").append(article);
}
$(".news-content").dotdotdot( { height:200 } );
$($(Mustache.render(footerTemplate, { link:"/news", target:"_self", content:"Read More"} ))).appendTo($("#news-container"));
} );
ajax("/ajax/getTweets.php", { count:3 }, function(data) {
$("#tweet-container").empty();
for (var i = 0; i < data.length; i++) {
var text = processTweetURLs(data[i].text);
var date = $.timeago(data[i].date);
var tweetData = { header:date, content:text };
var tweet = Mustache.render(tweetTemplate, tweetData);
$(tweet).appendTo($("#tweet-container"));
}
$(".twitter-content").dotdotdot();
$($(Mustache.render(footerTemplate, { link:"https://twitter.com/gp_studios", target:"_blank", content:"More Tweets"} ))).appendTo($("#tweet-container"));
} );
createGameBoxGrid(GAME_BOX_WIDE, ".featured-games-list", 3, [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}]);
$(".main-left").height( $(".main-center").height() );
createGameBoxGrid(GAME_BOX_SMALL, ".main-category-games-list", 9, [{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}]);
} );
getNews.php
<?php
include($_SERVER["DOCUMENT_ROOT"]."/class/Connection.php");
$mysql = new Connection();
$articles = [];
//SUBSTRING(news,1,1000)
if ($result = $mysql->query("SELECT id, title, news, author, dateadded FROM news ORDER BY dateadded DESC LIMIT 1")) {
while ($row = $result->fetch_assoc()) {
array_push($articles, [ "id"=>$row["id"], "title"=>$row["title"], "news"=>$row["news"], "author"=>$row["author"], "dateadded"=>$row["dateadded"] ] );
}
}
echo json_encode($articles);
?>
What I've written above is a bit waffley but was necessary to get across all the relevant info. So in simpler terms and phrased more like questions:
why is AJAX so slow compared to just running it before the page has fully loaded?
my AJAX PHPs echo a long and often complex JSON, how can I use the same script for AJAX and includes? I've tried surrounding the include in div tags (a method I don't like at all) but if the json contains html it get's interpreted as such and get's somewhat mangled.
Any general hints for making this work a lot better?
Upvotes: 2
Views: 5048
Reputation: 91792
The problem you are probably running into, is the fact that browsers limit the number of connections to the same server. See also this question on SO.
So if you put your code in a $(document).ready()
function, what actually happens, is that the DOM is ready, so all images start loading and your ajax call will not go through until there is a connection available to the same server.
So your ajax request can be fast, but it starts late, giving the impression of a long-during call.
You can solve this for example by putting all static assets like images on a different sub-domain.
However, you can also use the same script you use for your ajax call as an include so that you don't have to duplicate code. Then you can include it or call it using ajax and get the same results.
You could use something like:
if (!isset($some_enviroment_variable))
{
// ajax call
// set up environment
}
// do your php controller stuff
// output the results
Upvotes: 1