2

AJAX呼び出しで初期化するシングルトンに使用する正しいパターンを見つけようとしています。これは、私がすでに取り組んでいることの単純化された例です。

期待どおりに動作しますが、これは「正しい」方法ではなく、初期化子のコールバックを現在実行中の 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() ) });

または、これを行う簡単な方法はありますか?生活を楽にするために、ここで欠けている概念は何ですか?

4

1 に答える 1

2

ここで「正しい」方法を探しているので、いくつかの一般的な注意事項があります。

  1. シングルトンのクラスは必要ありません(JavaScriptはJavaではありません)。それをグローバルオブジェクトまたはそれ以上の関数にするだけです。

  2. $.Deferredはあなたの友達です。$.ajax約束を返します。

シングルトンの機能パターンは次のとおりです。

// 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プラグイン(開示:私が主な作成者です)があります。

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

シングルトンが多い、またはデータが遅延している大規模なプロジェクトの場合、グローバル変数よりも優れたスケールを注入します。

于 2012-06-23T16:03:13.680 に答える