缓存模式与回调

时间:2011-09-13 15:56:20

标签: javascript design-patterns coffeescript

我有一个处理数据的类。其他类可以为它们赋值,数据类将填充它们。

看起来像这样:

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

最后,我正在寻找的技术:“如果产品不存在,则从数据库填充它们”。我当时可能认为这可能是一种已知的模式,所以如果是这样的话,也可以了解有关它的信息。

2 个答案:

答案 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,因此您可以使用烦人的密钥,例如toStringvalueOf,这会在财产检查上标记真实性。

答案 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]

# ...