Knockout 扩展器导致 observable 在第一遍时成为 return 其默认值,无论输入如何

Knockout extender causing observable to return its default value on first pass regardless of input

我已经定义了一个名为 model.customDifficultySettings 的视图模型,其中的一部分如下所示。它使用一个名为 precision 的扩展器,它只是 Knockout.js 文档中显示的扩展器示例的重命名版本,用于四舍五入到 X 位小数。

ko.extenders.precision = function(target, precision) {
  //create a writable computed observable to intercept writes to our observable
  var result = ko
    .pureComputed({
      read: target, //always return the original observables value
      write: function(newValue) {
        var current = target(),
          roundingMultiplier = Math.pow(10, precision),
          newValueAsNum = isNaN(newValue) ? 0 : +newValue,
          valueToWrite =
            Math.round(newValueAsNum * roundingMultiplier) / roundingMultiplier;

        //only write if it changed
        if (valueToWrite !== current) {
          target(valueToWrite);
        } else {
          //if the rounded value is the same, but a different value was written, force a notification for the current field
          if (newValue !== current) {
            target.notifySubscribers(valueToWrite);
          }
        }
      }
    })
    .extend({ notify: "always" });

  //initialize with current value to make sure it is rounded appropriately
  result(target());

  //return the new computed observable
  return result;
};

model.customDifficultySettings = {
  econBase: ko
    .observable(0)
    .extend({ rateLimit: { timeout: 750 }, precision: 3 }),
};

在稍后的 makeGame() 函数中,我们确保我们的 model.customDifficultySettings.econBase() 可观察值与所选难度值

的值相匹配
        model.customDifficultySettings.econBase(
          difficultyInfo[model.newGameDifficultyIndex() || 0].econBase
        );
        console.log(model.customDifficultySettings.econBase());
        console.log(difficultyInfo[model.newGameDifficultyIndex() || 0].econBase);

第一个 运行 上的 difficultyInfo[model.newGameDifficultyIndex()].econBase 的值为 0.55。我希望控制台将两者都显示为 0.55,或者如果出现问题,两者都显示为 0。然而,对于可观察对象,返回的是 0,而对于输入其中的值,返回的是 0.55。

如果我在代码具有 运行 后从控制台查询 observable,它 returns 预期值为 0.55。

如果更改难度级别,导致 makeGame() 再次变为 运行,则所有值都设置正确。仅在第一个 运行 出现此问题。

我已经将问题追溯到精度扩展器。移除扩展器,一切都按预期工作。但是由于我刚刚复制了示例代码,所以我并不完全清楚它的作用以及为什么会出现此问题。

作为解决方法,我可以设置所有可观察到的默认值以匹配默认难度级别的值,但我宁愿避免这种情况。

出现问题是因为我先声明了一个 rateLimit。如果我反转它并首先声明 precision ,那么一切都会按预期进行。所以我的视图模型现在看起来像这样:

model.customDifficultySettings = {
  econBase: ko
    .observable(0)
    .extend({ precision: 3, rateLimit: { timeout: 750 } }),
};