I have a function which append some elements if a json file was loaded:
function loadNdraw(title, id){
$("#containerCharts").html("");
var date = $("#dateChart");
var jqJSON = $.getJSON("charts/" + id + "/" + date.val() + ".json");
jqJSON.done(
function(data){
$("#containerCharts").append(
"<div class='divStandard'>"
+ "<div class='titleChart'>"
+ "<div style='float: left;'>" + title + "</div>"
+ "<div style='float: right;'>" + data.lastUpdate +"</div>"
+ "<div style='clear: both;'></div>"
+ "</div>"
+ "<center><div id='" + id + "' class='bodyChart'></div></center>"
+ "</div>"
);
}
);
}
I call this function multiple times
loadNdraw("A", "a");
loadNdraw("B", "b");
loadNdraw("C", "c");
loadNdraw("D", "d");
My problem is that it does not load in this order.
Every time the page is loaded, the order of A,B,C,D is random.
How can I force it to be loaded in order?
I don't want to sort json.
-
Possible duplicate of Sort JSON array after $.getJSON excecutedHudsonPH– HudsonPH2018年12月07日 10:17:44 +00:00Commented Dec 7, 2018 at 10:17
2 Answers 2
You can use .promise() function in jquery
function loadNdraw(title, id){
var dfd = jQuery.Deferred();
$("#containerCharts").html("");
var date = $("#dateChart");
var jqJSON = $.getJSON("charts/" + id + "/" + date.val() + ".json");
jqJSON.done(
function(data){
$("#containerCharts").append(
"<div class='divStandard'>"
+ "<div class='titleChart'>"
+ "<div style='float: left;'>" + title + "</div>"
+ "<div style='float: right;'>" + data.lastUpdate +"</div>"
+ "<div style='clear: both;'></div>"
+ "</div>"
+ "<center><div id='" + id + "' class='bodyChart'></div></center>"
+ "</div>"
);
}
);
dfd.resolve(true);
}
Then you can simply call
$.when( loadNdraw("A", "a") ).then(
$.when( loadNdraw("B", "b") ).then(
//Some code
);
);
You can simply use .promise as per your need
Comments
The JSON scripts are being loaded asynchronously. The order in which the callbacks fire don't depend on the order in which you invoke loadNdraw, but the order in which jqJSON.done gets fired. The file that loads the fastest will cause its jqJSON.done method to be called first, and so on.
If you need these to be in order, you have a few options:
- Sort the HTML structure after all results have loaded (or each time a file loads)
- Load the charts sequentially, by calling
loadNdrawinside ofjqJSON.done, meaning that chartBwould only start loading afterAis done—this is likely to be much slower. - Populate the results in a temporary data structure, keep track of
whenall requests have completed, and then handle the DOM manipulation based on that data.
Option 3 seems to be your best bet in this situation:
function loadNdraw(title, id) {
$("#containerCharts").html("");
var date = $("#dateChart");
return $.getJSON("charts/" + id + "/" + date.val() + ".json");
}
var options = [
{ title: 'A', id: 'a' },
{ title: 'B', id: 'b' },
{ title: 'C', id: 'c' },
{ title: 'D', id: 'd' }
];
for (var option of options) {
option.promise = loadNdraw(option.title, option.id);
}
$.when(...options.map(o => o.promise)).done(function(...results) {
results.forEach(function(dataArray, idx) {
var title = options[idx].title;
var id = options[idx].id;
$("#containerCharts").append(
"<div class='divStandard'>"
+ "<div class='titleChart'>"
+ "<div style='float: left;'>" + title + "</div>"
+ "<div style='float: right;'>" + dataArray[0].lastUpdate +"</div>"
+ "<div style='clear: both;'></div>"
+ "</div>"
+ "<center><div id='" + id + "' class='bodyChart'></div></center>"
+ "</div>"
);
});
});
Note a couple of things here:
- The argument to
$.whenis a listing of of Thenables—objects like your jqXHR with athenmethod. You can pass it an array objects by expanding it with the...spreadoperator. - The callback for
$.whentakes a listing of response objects as its parameter, in the order in which the requests were made. They can be collected into an array using the...restparameter syntax.