Best strategy when filling HTML page via javascript and ajax - javascript

I have this HTML page that is filled via javascript with multiple ajax calls. I have this dictionary that is filled with some JSON text grabbed via ajax calls like in this example: (The actual code is over 1k lines)
var dict = {}
$.ajax({async: false, type: 'GET', url: '/page/1', success: function(data)
{
dict = JSON.parse(data);
// {'name': 'foo', 'image': '42', 'user': 'bar_user'}
$.ajax({async: false, type: 'GET', url: '/image/'+dict.image,
success: function(data)
{
dict.image = JSON.parse(data);
// {'low_res': 'l.jpg', 'high_res': 'h.jpg'}
}
$.ajax({async: false, type: 'GET', url: '/user/'+dict.user,
success: function(data)
{
dict.user = JSON.parse(data);
// {'email': 'bar#bar.com', 'image': '69'}
$.ajax({async: false, type: 'GET', url: '/image/'+dict.user.image,
success: function(data)
{
dict.user.image = JSON.parse(data);
// {'low_res': 'l_2.jpg', 'high_res': 'h_2.jpg'}
}
}
}
This dictionary is used to fill the page using some functions like so:
function fillImageDiv(img)
{
$('div#image_container > img').attr('src',img.high_res)
}
function fillUserDiv(user)
{
$('div#user_container > span').html(user.email);
$('div#user_container > img').attr('src', user.image.low_res);
}
fillImageDiv(dict.image);
fillUserDiv(dict.user);
Having this in mind, what would be the best way to fill the page?
Would it be better to fill the whole dictionary and then fill the divs, or to fill each div as soon as the JSON was loaded into the dictionary?
Making the ajax calls asynchronous would make the dict fill faster, even when there is no multi-threading in javascript?
What about calling fillImageDiv and fillUserDiv asynchronously?
Thank you!

In terms of performance, it would be best if you could just make one AJAX call to fill up your dictionary, and then fill in your <div> elements all in one go. Those synchronous AJAX calls are going to hurt the responsiveness of your site more than anything else.
If you can't combine the AJAX calls, and your site won't have its interface affected by not having each of the separate components (image and user) together, then it would definitely be better to have them separately updated asynchronously.
If you do need to have both of them together, then you can use an asynchronous control flow library such as caolan's async.js to more elegantly manage your parallel AJAX calls, and then update the DOM element in one go once the results are available.
In general, when you're talking about web and JavaScript performance, do the following things in order:
Minimize HTTP requests
Make your AJAX results cacheable
Minimize access to the DOM
The HTTP requests will generally be the bottleneck, and DOM manipulation right after that.

Related

Using multiple ajax calls in one javascript function

Thanks in advance for any help.
Is it bad practice and/or inefficient to use multiple $.ajax calls in one javascript function? I've been working on one and have a simple testing environment set up on my computer (apache server with php/mysql), and I've noticed that the server will crash (and restart) if I have multiple ajax calls.
I have two ajax calls currently: one passes 4 pieces of data to the php file and returns about 3 lines of code (pulling info from my sql database), the other simply gets the total rows from the table I'm working with and assigns that number to a javascript variable.
Is it just that my basic testing setup is too weak, or am I doing something wrong? See below for the two ajax calls I'm using:
$.ajax({
type: "GET",
url: "myURLhere.php",
cache: false,
data: {img : imageNumber, cap : imageNumber, width : dWidth, height : dHeight},
})
.done(function(htmlpic) {
$("#leftOne").html(htmlpic);
});
$.ajax({
type: "GET",
url: "myotherURLhere.php",
cache: false,
success: function(data) {
lastImage = data
}
})
Short answer: two ajax request on a page is absolutely fine.
Longer answer:
You have to find the balance between minimalising the number of ajax calls to the backend reducing the traffic and communication overhead; and still maintaining a maintainable architecture (so do not pass dozens of parameters in one call to retrieve everything - maybe only if you do it in a well designed way to collect every parameter to send)
Also most likely there's something wrong with your backend setup, try looking into webserver logs

How to merge multiple jsonp requests in a backbone.js model sync?

What am I trying to achieve?
There is a I am trying to update a nice jenkins radiator application made by Clayton Lengel-Zigich. It is a backbone.js application that fetches the status of a jenkins master server using its jsonp api and displays job status. I want to change this application to fetch from multiple masters and show the status for many jobs.
What have I tried?
I have tried to update the sync function to do two jsonp requests and then merge the result. The original file can be found here: https://github.com/clayton/jenkins-radiator/blob/master/src/radiator.js
sync: function(method, model, options) {
var paramsA = _.extend({
type: 'GET',
dataType: 'jsonp',
processData: true,
url: "http://serverA:8080/api/json?jsonp=?"
}, options);
var a = $.ajax(paramsA);
var paramsB = _.extend({
type: 'GET',
dataType: 'jsonp',
processData: true,
url: "http://serverB:8080/api/json?jsonp=?"
}, options);
var b = $.ajax(paramsB);
function MergeJobs(o, ob) {
for (var z in ob.jobs) {
o.jobs.push(ob.jobs[z]);
}
return o;
}
var joinedJson = []
a.done(function(jsonA) {
joinedJson = jsonA;
});
b.done(function(jsonB) {
MergeJobs(joinedJson, jsonB);
//joinedJson = jsonB;
})
return joinedJson;
},
What I got
I expected that I would be able to see the merged results in the webpage however I only see the results for one of the servers. Which server gets displayed is random, indicating to me that my merge is overwriting, not merging.
I don't know a lick of javascript so I am at the stage where I don't even know where to look next. Perhaps the _.extend section is what actually updates the model? If so, is there a way to achieve what I want another way?
You can create separate models and display them on the same If the models have the same structure I suggest you create an array containing all your models and then pass them to a collection. If your models are totally different then pass them to a view and have some logic in the view to handle all your models.
This site (http://backbonetutorials.com/) has some great tutorials to get started with models and collections just in case you haven't used backbone that much.
There's no guarantee as to which of your requests finishes first. If B finishes before A, it will merge jsonB into the empty joinedJson (simply setting it to jsonB) and then when A finishes it will overwrite joinedJson with jsonA.
That's not your only problem; at the time you return joinedJson there's no guarantee that either request has finished; you're treating asynchronous requests as if they were synchronous.

How to load new content to DIV without refreshing [duplicate]

This question already has answers here:
how to reload DIV content without refreshing whole page
(8 answers)
Closed 9 years ago.
I want to load new content from the server to the DIV without refreshing the whole page.
I tried the following
$.ajax({
type: "GET",
url: "http://127.0.0.1:8000/result/?age="+ ageData +"&occasion="+
occasionData +"&relationship="+ forData +"#",
success: function (response) {
$("#testDIV").html(response);
}
});
But the problem is the whole page is loading in <DIV id="testDIV">. I want to replace the old DIV with New DIV content returned from the server not with the whole page.
You can keep your same process sense you are interested in using AJAX directly and want to manage your done function (instead of success because .done() will replace it). Here is how...
.done(function(data) {
...
}
Inside of that done function, you can filter the page content to what you want. Simply request what you want to filter with jquery like this...
var $response = $(data);
var response_title = $response.filter(".title").html(); //I'm assuming you are trying to pull just the title (perhaps an < h1 > tag, in this little example, from the entire external page!
THEN!...
$("#testDIV").html(response_title);
With the done function, based on jQuery's API, you can use this format...
$.ajax({
type: "POST",
url: "some.php",
data: { name: "John", location: "Boston" }
}).done(function( msg ) {
alert( "Data Saved: " + msg );
});
So your final code may look something like this...
$.ajax({
type: "GET",
url: "ht.tp://127.0.0.1:8000/result/?age="+ ageData +"&occasion="+ occasionData +"&relationship="+ forData +"#"})
.done(function(response) {
var $response = $(response);
var response_title = $response.filter(".title").html();
$("#testDIV").html(response_title);
});
I like the answer by blackhawk. It uses the existing code with slight modification.
I would just condense it to a one line change like this:
$.ajax({
type: "GET",
url: "http://127.0.0.1:8000/result/?age="+ ageData +"&occasion="+
occasionData+"&relationship="+ forData +"#",
success: function (response) {
$("testDIV").html($(data).filter(".title").html());
}
});
The code you are displaying is actually correct.
The problem comes from what your server is providing.
What you are doing here is GETing a whole page via an AJAX call, and replacing the content of One div with that whole page.
Your server should not render the whole page for that call, but only the content of the div you wish to replace. If you are using framework like rails or symfony, they often provide an easy way to detect if the query is a normal GET request, or an AJAX call.
Basically you have 4 strategies at your disposal :
Make the requests to a specific endpoint that is used only for the ajax call and that returns the content of the div you wish to replace. And not the whole page.
Make the request to the same page, and detect if the request is a normal HTTP request or an AJAX call. Based on that, return the whole page or just the content of the div. You'll probably have to look for the helpers in your framework / toolbox documentation.
Make the AJAX request but ask for a JSON object. Transform your JSON in HTML on the client side to replace the content of the div. This is the "my app is just an API" approach. This is my personal favorite as this JSON endpoint can be used for other purposes (eg: a mobile app) since it carries only content, and not presentation. This also tends to be the fastest way in terms of performance since a significant part of the computation is done on the client side. On the con side, this requires you to write more JS.
Always render the whole page, and filter only what you need on the client side. This is balchawk approach. Benefit is that you don't have to modify your server, but you will waste processing time and bandwidth by returning a whole page, when only a subset is necessary.
$(function(){
$('.classloader.').on('click', function(e){
$.ajax({
type: "GET",
url: "http://127.0.0.1:8000/result/?age="+ ageData +"&occasion="+
occasionData +"&relationship="+ forData +"#",
beforeSend: function() {
$("#testDIV").hide();
$('div#loading').show();
},
success: function(html){
$("#testDIV").html($(html).filter("#mainContent").html()).show();
$('div#loading').hide();
}
});
return false;
});
})

javascript async woes

This is a newbie JavaScript question, but something I'm not quite sure how to google for help because I'm not sure how to describe the problem in an easy way.
I have a large, somewhat complex JSON that I need to manipulate so that I could reshape the JSON in a way that I get a list of only countries, cities, and sales.
The JSON itself isn't the issue for me, it's what I would like to do with it once I've received it. Basically, I'd like to create 3 separate objects/arrays from a large received JSON and have those 3 separate objects/arrays accessible for usage OUTSIDE of the $.ajax call. Yes, I think I could do all of this inside of the $.ajax success callback, but I'd rather have all the JSON processing done elsewhere. My pseudo JavaScript looks something like this:
var model = {
countries: [],
cities: [],
sales: [],
set: function(data) {
//manipulate data here so that model.countries, model.cities, model.sales are populated
}
};
$.ajax({
url: 'example.com/sample.json',
success: function(data) {
model.set(data); //is this the right way to do this?
}
});
$('#countries').html(model.countries);
$('#cities').html(model.cities);
$('#sales').html(model.sales);​
But because JavaScript executes asynchronously, the last 3 lines are always blank because the JSON hasn't been received yet.
So I guess my question is, how do I bind the results of my received JSON to a variable outside of the $.ajax scope so that I could use it wherever on the page?
The simple solution is this:
$.ajax({
url: 'example.com/sample.json',
success: function(data) {
model.set(data);
$('#countries').html(model.countries);
$('#cities').html(model.cities);
$('#sales').html(model.sales);​
}
});
If you want something more frameworky, then you could look at a something like Backbone.js.
Populate your HTML (i.e. update your view) in the AJAX success callback. i.e.
function updateView() {
$('#countries').html(model.countries);
$('#cities').html(model.cities);
$('#sales').html(model.sales);​
}
$.ajax({
url: 'example.com/sample.json',
success: function(data) {
model.set(data); //is this the right way to do this?
updateView();
}
});
Just put those 3 line in the success callback (you can also separate it into a function) and skip the model population.
There are frameworks that allow you to bind DOM elements to JS objects and their data, bu in this case it might be an overkill.

Multiple AJAX Call and JSON data

I have designed a website that takes a users input as search parameters and uses them to search a database using an AJAX call to a PHP page. In this AJAX call, I obviously have some data (formatted as a JSON file) that I manipulate and use in the "success" section of the ajax arguments.
Here's the problem--I want to be able to analyze the data from the narrowed search the user puts in against the data from the entire database population. How can I do this?
I thought I would just do another AJAX call, but the data from that call seems inaccessible from the outside, and I can't find any ways to "export" it outside the call.
Here is a shortened version of the code:
$.ajax({
url: URL for the search .php,
cache: false,
data: {
Various search parameters by the user
},
dataType:"json",
success:function(data){
Data manipulation and reading the resulting JSON
$.ajax({
url:URL2 for the population .php,
cache: false,
dataType:"json",
success:function(data){
population data stuff here
},
error: error stuff
}
error: error stuff
}
That's the only way I know to access the database thus far. How can I somehow pull the data out of that second AJAX so that I can use it in the first one?
Since your working with asynchronous callbacks you can't "extract" the data from the second call and use it in the first. What you will have to do is make the two calls and use the data from each within the second calls success callback. You can do this if rename the variables you're using with the success callback functions to be unique.
$.ajax({
url: /**/,
success:function(response1){
$.ajax({
url: /**/,
success:function(response2){
/* use both response1 and response2 here */
},
error: /**/
})
},
error: /**/
})
If you aren't using data from the first ajax call to make the second ajax call you can use something like jQuery.when to wait for both request to finish.

Categories

Resources