在迭代之间以超时递归循环遍历树

时间:2015-07-30 18:31:03

标签: javascript recursion rendering settimeout

我有这个对象树,表示如下(简化):

var root = [
    { name: 'child1',
      data: 'other_data',
      children: [ {
         name: 'grand_child1',
         data: 'other_data',
         children: [...]
      }, ... ]
    },
    { name: 'child2',
      data: 'other_data',
      children: [ {
         name: 'grand_child2',
         data: 'other_data',
         children: [...]
       }, ... ]
    }
]

我需要循环遍历此对象树并根据子节点中提供的数据实例化对象,但此过程需要几秒钟,并且它会同时冻结浏览器。

我需要在循环的迭代之间有一个超时,以使浏览器有机会清除事件队列。

我该怎么做?

这就是我目前正在循环遍历它们的方式,没有超时。我目前正在使用相互递归模式。

function performSingleNodeComputation(node) {
  performHeavyComputation(node.data)
  if(node.children) {
    performMultipleNodeComputation(node.children);
  }
}

function performMultipleNodeComputation(nodes) {
  nodes.forEach(function (node) {
    performSingleNodeComputation(node);
  });
}

performMultipleNodeComputation(root);

重申一下,我需要在每次performHeavyComputation

的调用之间超时

1 个答案:

答案 0 :(得分:1)

2个简单的解决方案

第一种方法:像这样延迟第一级节点计算

var root = [{ 
      name: 'child1',
      data: 'other_data0',
      children: [{
         name: 'grand_child1',
         data: 'other_data1',
         children: null
      }]
    }, {
      name: 'child2',
      data: 'other_data2',
      children: [{
         name: 'grand_child2',
         data: 'other_data3',
         children: null
      }]
    }
];


function performHeavyComputation(data){
  console.log(data);
}

function performSingleNodeComputation(node) {
  performHeavyComputation(node.data);
  if (node.children) {
    performMultipleNodeComputation(node.children);
  }
}

function performMultipleNodeComputation(nodes) {
  var i = 0;
  function inner() {
    performSingleNodeComputation(nodes[i]);
    ++i;
    if (i < nodes.length){
      setTimeout(inner, 1000);
    }
  }
  inner();
}

performMultipleNodeComputation(root);

第二种方法:用节点组合数组,并以延迟

逐步执行大量操作
var root = [{ 
      name: 'child1',
      data: 'other_data0',
      children: [{
         name: 'grand_child1',
         data: 'other_data1',
         children: null
      }]
    }, {
      name: 'child2',
      data: 'other_data2',
      children: [{
         name: 'grand_child2',
         data: 'other_data3',
         children: null
      }]
    }
];

function delayedProccessing (root) {

  var list = [];

  function delayComputation(data) {
    list.push(data);
  }

  function performSingleNodeComputation(node) {
    delayComputation(node.data);
    if (node.children) {
      composeList(node.children);
    }
  }

  function composeList(nodes) {
    for (var i = 0; i < nodes.length; ++i){
      performSingleNodeComputation(nodes[i]);
    }
  }

  function performHeavyComputation(data){
    console.log(data);
  }

  function proccessList() {
    var i = 0;
    function inner () {
      performHeavyComputation(list[i]);
      ++i;
      if (i <= list.length){
        setTimeout(inner, 1000);
      }
    }
    inner();
  }

  composeList(root);

  proccessList();
}

delayedProccessing(root);