递归循环遍历树,在迭代之间设置超时

Recursively loop through a tree with a timeout in between iterations

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

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

之间有一个超时

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);

第二种方法:将数组与节点组合在一起,并通过延迟执行 1 对 1 的繁重操作

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);