2012-04-15 7 views
0

Ich entwickle ein jQuery-Plugin, das vorgibt, Elemente auf der Seite automatisch in Abhängigkeit von der Browsersprache des Benutzers zu übersetzen. Übersetzungen werden in .json-Dateien gespeichert.Wie man Versprechen zurückgibt, das mit dem Ergebnis mehrerer Funktionen auflösen wird?

Wenn Sie das Plugin aufrufen, übergeben Sie einen Paketnamen (oder ein Array von ihnen), und dann wird es versuchen, die Sprachdatei in der folgenden Art und Weise zu laden:

  • Wenn die Sprache des Browsers einfach ist, zum Beispiel 'en' und Sie nur ein Paket angegeben haben, wird es versuchen, die folgende zu laden: packageName-en.json
  • Wenn die Sprache zusammengesetzt ist, Browser, zum Beispiel ‚en-US‘ es die gleichen wie zuvor, aber mit laden werden versuchen: packageName-en.jsonUNDpackageName-en-US.json
  • Wenn mehr als ein Paket angegeben ist, wird versucht, für jedes Paket einen der beiden vorherigen Pfade zu verfolgen.

Also, im Plugin Ich habe diese:

$.fn.Translator = function(pkg, options){ 
    Translator.initialize(pkg, options).done(function(){ 
     return this.each(Translator.translate); 
    });    
}; 

Also, irgendwo in meiner Initialisierungsfunktion, ich habe dies:

loadLanguages : function(){ 
    $.each(self.options.packages,function(i, pkg){ 

    }); 
} 

, die diese Funktion aufruft:

getLanguage : function(pkg, language){ 
    var self = this, url; 
    if (self.options.path) 
     url = self.options.path + '/'; 
    url += [pkg, language].join('-'); 

    return $.ajax ({ 
     url : url, 
     dataType : "json", 
     cache : self.options.cache 
    }); 
} 

Das Problem ist, dass diese Funktion wahrscheinlich aufgerufen wird y mehrere Male, ich weiß nicht, wie man initialize macht, um ein Versprechen zurückzugeben, das aufgelöst wird, sobald ALLE Funktionen aufgerufen worden sind.

Antwort

2

Ich weiß, dass Sie eine Antwort bereits akzeptiert, aber es gibt eine viel einfachere Art und Weise: $.when verwenden.

function loadLanguages() { 
    return $.when.apply($, $.map(self.options.packages, function(pkg) { 
     return getLanguage(pkg, language); 
    })); 
} 
+0

Obwohl ich eine Antwort angenommen habe, denke ich, deine ist besser. Das war die Art von Lösung, nach der ich suchte und die andere Art schien irgendwie hackisch. Vielen Dank Julian :) –

0

Um dieses Problem zu lösen, können Sie einen Dummy Deferrer (baseDfr) erstellen und den Dummy als Ergebnis initialize() zurückgeben. Die Idee hier ist, baseDfr.resolve() zu rufen, wenn alle Anrufe erledigt sind. Wir verfolgen die Anzahl der Anrufe, die mit einem Zähler durchgeführt werden. Wenn der Zähler 0 erreicht, rufen wir baseDfr.resolve(). Wir wissen, wenn ein Aufruf erfolgt mit der then() oder done() Methode auf dem zurückgegebenen Deferrer von $.ajax.

Der Code, um dies zu lösen, kann unten gefunden werden. Ein Arbeitsbeispiel (auf einigen Divs) finden Sie auch hier: http://jsfiddle.net/c5NBr/. Öffnen Sie die Konsole, um zu sehen, dass die Nachrichten in der richtigen Reihenfolge angezeigt werden.

var packages = []; 
var count = 0; 
var baseDfr = $.Deferred(); 
var language = "en"; 

function resolveFunction() { 
    // By using this approach it is possible to pass a 
    // parameter to this resolve function. 
    return function(){ 
     if (!(--count)) { 
      // Until count is 0, we won't resolve the base 
      // deferrer object. 
      // As long as this isn't called, the function 
      // done() of initialize won't be called either. 
      baseDfr.resolve(); 
     }  
    }; 
} 

function getLanguage (pkg, language){ 
    var self = this, url; 
    if (self.options.path) 
     url = self.options.path + '/'; 
    url += [pkg, language].join('-'); 

    return $.ajax ({ 
     url : url, 
     dataType : "json", 
     cache : self.options.cache 
    }).promise(); 
} 

function loadLanguages() { 
    $.each(self.options.packages,function(i, pkg){ 
     getLanguage(pkg, language).then(resolveFunction()); 
    }); 

    return baseDfr.promise();     
} 

function initialize(options) { 
    packages = options.packages; 
    count = options.packages.length;  

    return loadLanguages(); 
} 

var options = { 
    packages : $('div')   
}; 

initialize(options).done(function(){ 
    // This will only be called when baseDfr.resolve() is called. 
    console.log("Fired all getLanguage()."); 
}); 
Verwandte Themen