为什么在以下代码中list
数据量很大时,我的浏览器会变慢:
var list = [];
/*
Creating some huge dummy data
Interstingly, when I change the value of i from 10000
to 100000, the browser hangs(becomes unresponsive)
*/
for(i=0;i<10000;i++){
list.push(i);
}
/*Recursive function*/
var nextListItem = function() {
var item = list.pop();
if (item) {
console.log(item);
// process the list item...
nextListItem();
}
};
nextListItem(); // Commented this as browser becomes unresponsive.
我无法从谷歌找到我的问题的直接答案,所以虽然得到SO专家的帮助。我假设它与浏览器内存有关,因为我可以看到循环以很快的速度启动并慢慢减速并变得无响应。但不确定为什么?
答案 0 :(得分:6)
JavaScript没有尾部调用消除。因此,如果以递归方式遍历列表,则会浪费大量资源。最终你甚至可能会耗尽堆栈空间。
这个问题的一个可能的解决方案是异步调用尾调用,以便在尾调用函数开始执行之前main函数完成执行。这可确保堆栈空间不会增加:
var list = [];
for (var i = 0; i < 10000; i++) list.push(i);
var start = new Date;
nextListItem();
function nextListItem() {
var item = list.pop();
if (item) {
console.log(item);
setTimeout(nextListItem, 0);
} else console.log(new Date - start);
}
有关详细信息,请参阅以下问题:
What's the difference between a continuation and a callback?
编辑:更快的解决方案(正如T.J.Crowder所建议的那样):
var list = [];
for (var i = 0; i < 10000; i++) list.push(i);
var start = new Date;
nextListItem();
function nextListItem() {
var item = list.pop();
if (item) {
console.log(item);
if (item % 100) nextListItem();
else setTimeout(nextListItem, 0);
} else console.log(new Date - start);
}
循环更缓慢,因为它以100个项目的突发打印到控制台。但是它可以更快地完成执行。
答案 1 :(得分:0)
我建议使用Javascript Promise。
function nextListItem2 (list) {
return new Promise(function(resolve, reject) {
var item = list.pop();
if(item) {
console.log(item);
return nextListItem(list);
} else {
resolve();
}
});
}
nextListItem2(list);