2012-06-23 2 views
2

J'essaie de trouver le motif correct à utiliser pour un singleton qui s'initialise avec un appel AJAX. Ceci est un exemple simplifié de ce que j'ai déjà travaillé. Cela fonctionne comme prévu, mais j'ai l'impression que ce n'est pas la bonne façon et qu'il y a un moyen d'accrocher le callback de l'initialiseur dans l'appel de succès de la requête ajax en cours, et je suis inquiet qu'il y ait pourrait être une condition de concurrence avec l'approche de tableau. Suis-je sur la bonne voie ici?javascriptMVC singleton avec le motif de conception de l'initialiseur AJAX

var singletonObj; 
$.Class("SingletonTest", { 
    init: function(onSuccess) { 
    if (singletonObj) { 
     if (singletonObj.ajaxLoaded) { 
     onSuccess(singletonObj); 
     } 
     else { 
     singletonObj.callbacks.push(onSuccess); 
     } 
    } 
    else { 
     singletonObj = this; 
     singletonObj.callbacks = new Array(onSuccess); 
     singletonObj.count=0; 

     $.ajax({ 
     url: "/path/to/json/config", 
     method: "GET", 
     success: function (res) { 
      singletonObj.data = res.meta_data; 
      singletonObj.ajaxLoaded = true 

      singletonObj.callbacks.forEach(function(callback) { 
      callback(singletonObj); 
      }); 
     } 
     }); 
    } 
    }, 
    counter: function() { 
    return this.count++; 
    } 
}); 

new SingletonTest(function(obj) { console.log("First call: "+obj.counter()) }); 
new SingletonTest(function(obj) { console.log("Second call: "+obj.counter()) }); 
new SingletonTest(function(obj) { console.log("Third call: "+obj.counter()) }); 

Ou y a-t-il une manière plus simple de faire ceci? Quel concept me manque-t-il ici pour rendre la vie plus facile?

+0

pourrait améliorer la pertinence des commentaires! – cliveholloway

+2

En outre, forEach ne fonctionnera pas dans IE et le nouveau tableau() devrait être évité (écrire [onSuccess] à la place). – noah

Répondre

2

Puisque vous cherchez la façon dont voici quelques remarques générales « correcte »:

  1. Vous n'avez pas besoin d'une classe pour un singleton (JavaScript est pas Java). Juste en faire un obj global ou mieux encore une fonction.

  2. $.Deferred est votre ami. $.ajax renvoie une promesse.

Voici un schéma fonctionnel pour singletons:

// creates a lazy singleton from a factory function 
function singleton(factory) { 
    var deferred; 
    return function() { 
     return deferred || (deferred = factory()); 
    }; 
} 

// declare your specific singleton 
var SingletonTest = singleton(function() { 
    return $.ajax({ 
     url: "/path/to/json/config", 
     method: "GET" 
    }).pipe(function(obj) { 
     // pipe lets you modify the result 
     // here we add the counter method 
     var count = 0; 
     obj.counter = function() { 
      return count++; 
     }; 
     return obj; 
    }); 
}); 

// use it 
SingletonTest().then(function(obj) { 
    console.log("First: "+obj.counter()); 
}); 

SingletonTest().then(function(obj) { 
    console.log("Second: "+obj.counter()); 
}); 

Si vous vous trouvez en utilisant ce modèle beaucoup, il y a une JMVC plugin (divulgation: Je suis l'auteur principal) qui met en œuvre une fonctionnelle forme d'injection de dépendance.

Si vous deviez utiliser Inject, il ressemblerait à ceci:

var cache = Inject.cache(); 
var Injector = Inject(
    cache.def('SingletonTest',function() { 
     return $.ajax({ 
      url: "/path/to/json/config", 
      method: "GET" 
     }).pipe(function(obj) { 
      var count = 0; 
      obj.counter = function() { 
       return count++; 
      }; 
      return obj; 
     }); 
    }) 
); 

var logCount = Injector('SingletonTest',function(obj,message) { 
    console.log(message+obj.counter()); 
}); 

logCount("First:"); 
logCount("Second:"); 

Pour les grands projets avec beaucoup de singletons ou des données simplement reportées, l'injection échelles mieux que les variables globales.

+0

Merci beaucoup pour votre réponse détaillée. Je suis encore en train d'apprendre des modèles modernes de design JS, et celui-ci me faisait trop gratter la tête. – cliveholloway