我正在尝试找出用于使用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() ) });
或者有更简单的方法吗?我在这里想到的什么概念会让生活更轻松?
答案 0 :(得分:2)
由于您正在寻找“正确”的方式,因此这里有一些常规说明:
您不需要单例类(JavaScript不是Java)。只是让它成为一个全球性的obj或更好的功能。
$.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 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:");
对于有大量单身或只是延迟数据的大型项目,注入比全局变量更好的比例。