Ich lasse den überflüssigen Bloat aus deinem Beispiel Mal weg, und konzentriere mich in meiner Antwort auf das Skelett deiner Anwendung. Die anderen Antwortenden haben dir ja schon erklärt, dass dein Problem auf asynchronen Kontrollfluss zurückzuführen ist, und das Promises ein populäres Entwurfsmuster zu dessen Bewältigung sind. Du nutzt sogar schon ohne es zu wissen Promises, nämlich wenn du die done()-Methode von jQuery benutzt.
function getData() {
var url;
// ...
$.getJSON(url).done(function(data){
// (1)
//tu etwas mit den JSON-Daten
}).fail(function(){
//tu etwas anderes im Fehlerfall
});
// (2)
}
// (3)
An Stelle (1) ist dir ja schon bewusst, wie du auf das JSON-Erbenis zugreifen kannst. An den Stellen (2) und (3) hast du noch Schwierigkeiten. Der Clou dabei ist einfach, das Anfrage-Objekt (das Promise von jQuery) an den beiden nachfolgenden Stellen wieder zu verwenden. Diese Wiederverwendung erreicht man, indem man sich das Anfrage-Objekt in einer Variabeln zwischenspeichert (2) bzw. indem man das Promise von der Funktion zurückgibt (3).
function getData() {
var url;
// ...
var request = $.getJSON(url);
request.done(function(data){
// (1)
//tu etwas mit den JSON-Daten
}).fail(function(){
//tu etwas anderes im Fehlerfall
});
// (2)
request.done(function(data){
//tu etwas mit den JSON-Daten
});
return request;
}
// (3)
getData().done(function(data){
//tu etwas mit den JSON-Daten
});
Das spiegelt deinen Problemfall noch nicht exakt wieder, denn man kann auf diese Weise nicht die JSON-Daten an Stelle (1) weiterverarbeiten und an den Stellen (2) und (3) mit dem Zwischenergebnis weiter machen. Zu diesem Zweck, kann man sich ein eigenes Promise basteln (beachte, dass ich mich im Beispiel für native Promises entschieden habe und gegen jQuerys Variante).
function getData() {
var url;
// ...
var promise = new Promise(function(resolve,reject){
$.getJSON(url).done(function(data){
// (1)
//tu etwas mit den JSON-Daten
var result = doSomething(data);
resolve(result); // Hier wird das Zwischenergebnis für die nachfolgenden Schritte bereit gestellt
}).fail(function(){
//tu etwas anderes im Fehlerfall
reject(); // Hier wird der Fehlerfall propagiert
});
});
// (2)
promise.then(function(data){ // .then() ist das Pendant zu jQuerys .done()
// tu etwas mit dem Zwischenergebnis von Schritt (1)
});
return promise;
}
// (3)
getData().then(function(data){
// tu etwas mit dem Zwischenergebnis von Schritt (1)
});
(Code ist ungetestet)