我有一个处理数据的类。其他类可以为它们赋值,数据类将填充它们。
看起来像这样:
class Data
constructor : ->
@products = null
populateProducts : (callback)=>
ajaxCall (data)=>
@products = data
callback()
allProducts : (list)=>
if @products?
list = @products
else
@populateProducts => allProducts list
我面临的问题是我添加的每个方法都必须检查产品是否存在。所以我正在研究如何使代码的这一部分可重用。
我试过的一种方法如下:
productsCheck : (callback)=>
if @products?
callback()
else
@populateProducts => products callback
使用这种方法,我可以简化所有产品:
allProducts : (list)=>
@productsCheck => list = @products
最后,我正在寻找的技术:“如果产品不存在,则从数据库填充它们”。我当时可能认为这可能是一种已知的模式,所以如果是这样的话,也可以了解有关它的信息。
答案 0 :(得分:4)
Underscore有_.memoize
将函数调用的结果缓存到id(即第一个参数)。
Memoization是一种易于实施的模式。
var memoize = function _memoize(f) {
var cache = {};
return function _intercept(arg) {
if (cache[arg]) return cache[arg];
return (cache[arg] = f.apply(this, arguments));
}
};
您必须调整此模式以使其与回调异步工作。
这里的完整性是_.memoize
代码:
_.memoize = function(func, hasher) {
var memo = {};
hasher || (hasher = _.identity);
return function() {
var key = hasher.apply(this, arguments);
return hasOwnProperty.call(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments));
};
};
Underscore似乎接受hasher
作为第二个参数,它将根据参数生成唯一键。 (默认为下划线标识功能)。
它似乎也使用hasOwnProperty
,因此您可以使用烦人的密钥,例如toString
和valueOf
,这会在财产检查上标记真实性。
答案 1 :(得分:1)
因为您异步加载@products
,并且对象上的每个方法都必须(可能)等待@products
加载,所以对象上的每个方法都是异步的,需要将其结果返回给回调。没有办法解决这个问题;你不能使异步JS代码同步。 allProducts
不能只返回一个值。
以下是您应该做的事情:首先,更改populateProducts
,以便它不会进行Ajax调用,如果它不需要:
populateProducts : (callback) =>
if @products?
callback()
else ajaxCall (data) =>
@products = data
callback()
然后启动使用@products
并调用@populateProducts
的每个方法,如下所示:
allProducts : (callback) =>
@populateProducts =>
callback @products
firstProduct: (callback) =>
@populateProducts =>
callback @products[0]
# ...