【问题标题】:Loop through big Javascript object with setTimeout使用 setTimeout 循环遍历大型 Javascript 对象
【发布时间】:2017-02-14 13:21:44
【问题描述】:

如何遍历非常大的对象元素而不导致浏览器挂起?

我可以像这样使用setTimeout/setInterval 轻松循环数组:

var i = 0;
var l = arr.length;
var interval = window.setInterval(function(){
   var k = 100; // process 100 items on each Timeout
   var element;
   while(k--) {
      if (i == l) {
          return clearInterval(interval);
      }
      element = arr[i++];
      // ... work here ...
   }
}, 100);

但是对于非常大的物体,我有哪些选择?

  • 首先读取密钥for(k in arr) 不是一种选择,因为这将是一个我想避免的大循环。
  • 我不能 .splice() 对象,因为它不是数组。

目前我正在创建这样的数组 [{k: .., v:...},{k: .., v:...},{k: .., v:...},{k: .., v:...},{k: .., v:...},{k: .., v:...},{k: .., v:...},...] 但这太浪费空间了。

【问题讨论】:

  • 定义“非常大的对象元素”
  • Object.keys() 为您提供可以迭代的属性名称数组。
  • Web workers 或服务器端是线程工作的不错选择。但仅限于网络工作者的现代浏览器。
  • @CasparKleijne 100,000,000,000 个元素。非常大 :) 开玩笑说人们使用旧电脑,即使是 1000 个元素的小物体也会让浏览器挂起
  • 减少 k/timeout 间隔,或者如果实际上有 1000 亿个元素,则可以使用 web worker

标签: javascript arrays loops object


【解决方案1】:

您可以使用 Object.keys 对对象执行完全相同的逻辑

var i = 0;
var keys = Object.keys( myObj );
var l = keys.length;
var interval = window.setInterval(function(){
   var k = 100; // process 100 items on each Timeout
   var element;
   while(k--) {
      if (i == l) {
          return clearInterval(interval);
      }
      element = myObj[ keys[i++] ];
      // ... work here ...
   }
}, 100);

但是对于数以百万计的密钥,您应该寻找不同的解决方案,因为您不想循环那么多。也许将所有内容分成批次等。

因此我的问题变成了,有时您实际上需要同时在内存中存储数百万个对象,因为这听起来像是一个设计问题。

【讨论】:

  • 忽略“百万”我只是在开玩笑,你的回答很完美。对于具有 100000 个元素的对象 Object.keys 在不到 30 毫秒内返回值。实际上,我要处理的对象要小得多,但我宁愿将极端情况作为测试用例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-16
  • 2014-07-14
  • 2013-03-09
  • 2015-09-16
  • 1970-01-01
  • 2016-07-08
  • 2015-10-15
相关资源
最近更新 更多