具有AJAX初始化设计模式的javascriptMVC单例

时间:2012-06-23 04:24:26

标签: jquery ajax singleton javascriptmvc

我正在尝试找出用于使用AJAX调用初始化的Singleton的正确模式。这是我已经工作的简化示例。

它按预期工作,但我感觉这不是“正确的”方式,并且有一些方法可以将初始化程序的回调挂钩到当前运行的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() ) });

或者有更简单的方法吗?我在这里想到的什么概念会让生活更轻松?

1 个答案:

答案 0 :(得分:2)

由于您正在寻找“正确”的方式,因此这里有一些常规说明:

  1. 您不需要单例类(JavaScript不是Java)。只是让它成为一个全球性的obj或更好的功能。

  2. $.Deferred是你的朋友。 $.ajax会返回一个承诺。

  3. 以下是单身人士的功能模式:

    // 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());
    });
    

    如果你发现自己经常使用这种模式,那么有一个JMVC plugin(披露:我是主要作者)实现了依赖注入的功能形式。

    如果你使用Inject,它将如下所示:

    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:"); 
    

    对于有大量单身或只是延迟数据的大型项目,注入比全局变量更好的比例。