Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何优化KnockoutJS pureComputed函数?_Javascript_Performance_Knockout.js - Fatal编程技术网

Javascript 如何优化KnockoutJS pureComputed函数?

Javascript 如何优化KnockoutJS pureComputed函数?,javascript,performance,knockout.js,Javascript,Performance,Knockout.js,我开始注意到我的小游戏表现不佳,因为我在游戏中加入了更多的KO元素 我有一个ResourcesVM,它包含所有Resources作为一个可观察的数组。此存储MainResource对象包含名称、总数量、总容量,以及用于存储此Resource的所有Building对象的列表 示例:岩石和木材在其“仓库建筑”中都有相同的库存建筑对象。此Ressource对象存储在RessourcesVM的AllResources observableArray中 我正在尝试创建一个显示资源数量的小中心 在我的mai

我开始注意到我的小游戏表现不佳,因为我在游戏中加入了更多的KO元素

我有一个ResourcesVM,它包含所有Resources作为一个可观察的数组。此存储MainResource对象包含名称、总数量、总容量,以及用于存储此Resource的所有Building对象的列表

示例:岩石和木材在其“仓库建筑”中都有相同的库存建筑对象。此Ressource对象存储在RessourcesVM的AllResources observableArray中

我正在尝试创建一个显示资源数量的小中心

在我的mainResource对象中,我有一个pureComputed函数要计算,我决定在这里解析整个对象,以便您更好地理解该对象:

function MainRessource(data) {
  var self = this;

  self.Name = data.Name;
  self.IconCss = data.IconCss;

  //Incremented by the BuildingVM once the building's construction is completed
  self.TotalQte = ko.observable(isNaN(data.TotalQte) ? 0 : data.TotalQte);
  self.TotalCapacity = ko.observable(isNaN(data.TotalCapacity) ? 0 : data.TotalCapacity);


  self.ProductionRate = ko.observable(isNaN(data.ProductionRate) ? 0 : data.ProductionRate);
  self.getProductionRatePerSecond = ko.pureComputed(function() {
    var p = Game.app.cf.refreshEvery/self.ProductionRate();
    if(p > 0 && p != 'Infinity')
      return p;
    return 0;
  });

  if(data.StoredIn) { //TODO implement this properly
    self.StoredIn = data.StoredIn;
  } else {
    console.log("Warning: Ressource with name "+self.Name+" doesn't appear to have a StoredIn set.");
  }
  self.StorageBuildings = ko.observableArray([]);
  self.ProductionBuildings = ko.observableArray([]);

  self.OccupyingSpace = ko.observable(data.OccupyingSpace);


    self.getMaxCapacity = ko.pureComputed(function() {

      if(self.Name == "Energy") {
        //Energy is not "stored" in any buildings, return direct value
        var v = Math.floor(self.TotalCapacity());

      } else if(self.Name == "Wood") {
        //To calculate max wood capacity,, remove the space Rock occupies
        var r = Game.app.Ressources.AllRessources()[2];
        r = (r.TotalQte() / r.OccupyingSpace());

        var v = Math.floor((self.TotalCapacity()-r)/self.OccupyingSpace());

      } else if(self.Name == "Rock") {
        //To calculate max wood capacity,, remove the space Wood occupies
        var w = Game.app.Ressources.AllRessources()[1];
        w = (w.TotalQte() / w.OccupyingSpace());

        var v = Math.floor((self.TotalCapacity()-w)/self.OccupyingSpace());

      } else if(self.StoredIn == "FoodStorage") {
        var startWith = self.TotalCapacity(); //Total food capacity
        //For each Ressource that is stored in FoodStorage building type, remove the occupying space of that ressource
        for(var l = Game.app.Ressources.AllRessources.length, i = 0; i < l; i++) {
            //Skip the ressource we are calculating for
            if(Game.app.Ressources.AllRessources.StoredIn == 'FoodStorage' && Game.app.Ressources.AllRessources.Name != self.Name) {
              var w = Game.app.Ressources.AllRessources()[i];
              startWith -= (w.TotalQte() / w.OccupyingSpace());
            }
          }

          var v = Math.floor(startWith/self.OccupyingSpace());
      }

      if(isNaN(v) || v <= 0)
        return 0;

      return v;
    });

}
函数MainResource(数据){
var self=这个;
self.Name=data.Name;
self.IconCss=data.IconCss;
//建筑施工完成后,由BuildingVM递增
self.TotalQte=ko.observable(isNaN(data.TotalQte)?0:data.TotalQte);
self.TotalCapacity=ko.observable(isNaN(data.TotalCapacity)?0:data.TotalCapacity);
self.ProductionRate=ko.observable(isNaN(data.ProductionRate)?0:data.ProductionRate);
self.getProductionRatePerSecond=ko.pureComputed(函数(){
var p=Game.app.cf.refreshEvery/self.ProductionRate();
如果(p>0&&p!=“无穷大”)
返回p;
返回0;
});
如果(data.StoredIn){//TODO正确实现此操作
self.StoredIn=data.StoredIn;
}否则{
console.log(“警告:名为“+self.name+”的Ressource似乎没有设置StoredIn。”);
}
self.StorageBuildings=ko.observearray([]);
自产建筑=ko.observearray([]);
self.OccupyingSpace=ko.可观察(data.OccupyingSpace);
self.getMaxCapacity=ko.pureComputed(函数(){
如果(self.Name==“能量”){
//能量不会“储存”在任何建筑物中,而是直接返回值
var v=数学层(self.TotalCapacity());
}else if(self.Name==“Wood”){
//要计算最大木材承载力,请删除岩石占用的空间
var r=Game.app.Ressources.AllRessources()[2];
r=(r.TotalQte()/r.OccupyingSpace());
var v=数学层((self.TotalCapacity()-r)/self.OccupyingSpace());
}else if(self.Name==“Rock”){
//要计算最大木材容量,请删除木材占用的空间
var w=Game.app.resources.allresources()[1];
w=(w.TotalQte()/w.OccupyingSpace());
var v=数学层((self.TotalCapacity()-w)/self.OccupyingSpace());
}else if(self.StoredIn==“食品仓库”){
var startWith=self.TotalCapacity();//总食物容量
//对于存储在FoodStorage building type中的每个Ressource,请删除该Ressource的占用空间
对于(var l=Game.app.resources.allresources.length,i=0;i
我知道pureComputed函数目前有点混乱,我仍在努力找出最好的方法

我应该在RessourcesVM中移动getMaxCapacity函数吗?这会给我带来一些性能优势吗

有关逻辑的更多信息: 你可以有多个库存,库存存储木材和岩石。岩石使用2个空格,木材使用1个空格(这就是为什么在前面的代码中存在“占用空间”的原因) 你可以有多个粮仓,粮仓里有苹果和面包

我需要知道所有粮仓中有多少苹果,以及所有粮仓的总容量

谢谢你的帮助


edit在我的解释中将Ressource更改为MainRessource,以反映代码中提供的真实对象的名称。

我不确定您的确切性能问题是什么,但您可以尝试将计算结果扩展为
.extend({deferred:true})
。这确保了当您连续修改其依赖项时,您的计算结果只重新评估一次。(例如,将
n
次推到
AllResources
会导致
1
计算)。谢谢,我确保我的pureComputed“正常”“,以前从未使用过KO,我觉得这个函数太大了。但是的,我已经设置了
KO.options.deferUpdates=false;KO.options.rateLimit=25;
;)thxI仍然认为您可以改进计算方法,但我认为您不必太担心性能。改进要点:由于
Name
不可见,我建议使用iLife来确保Main
if
语句只执行一次。很好,非常感谢!
<!-- ko with: Ressources -->
  <!-- ko foreach: AllRessources -->
  <div class="hub" >
    <i data-bind="css: IconCss"></i>
    <span data-bind="text: Math.floor(TotalQte())"></span>/<span data-bind="text: getMaxCapacity()"></span>
    (<span data-bind="text: getProductionRatePerSecond()"></span>) <span data-bind="meter: {value: TotalQte, max: TotalCapacity }" class="meter-sm"></span>
  </div>
  <!-- /ko -->
<!-- /ko -->