setTimeout 如何防止潜在的 stackoverflow
How does setTimeout prevent potential stackoverflow
一个例子:
var list = readHugeList();
var nextListItem = function() {
var item = list.pop();
if (item) {
setTimeout( nextListItem, 0);
// ^^^^^^^^ this line
}
};
setTimeout
的使用如何防止此处潜在的 Whosebug?我了解事件队列和堆栈的概念,但我很难将两者联系起来。
设置超时不会导致堆栈溢出,因为它是异步的。它只会将回调放入事件队列,而不会阻止执行。
第一种情况:
setTimeout 只是将回调放到事件队列中,父函数在不占用堆栈的情况下退出。
即使超时为0毫秒,也会在下一个事件循环中调用,因此不会阻塞执行中的代码
var nextListItem = function() {
var item = list.pop();
if (item) {
setTimeout( nextListItem, 0);
}
};
第二种情况:
父级调用子函数将新条目放入堆栈,即使父级未从堆栈中清除。
最终更多的递归调用会破坏堆栈。
var nextListItem = function() {
var item = list.pop();
if (item) {
nextListItem();
}
};
考虑 setTimeout(, 0)
在此函数终止后将函数安排到 运行。 nextListItem()
不会被递归调用,而是被JS环境再次调用
如果你这样做 var r() = function() { r(); };
函数会调用自身并溢出堆栈。如果您这样做 var r() = function() { setTimeout(r, 0); };
,那么 r()
将在 r()
终止后安排到 运行,并且它将永远 运行。
使用 setTimeout(, 0)
而不是 while
或 for
来遍历列表是有原因的:它允许浏览器在下一次调用 [= 之前处理其他事件19=]。如果列表很长,这可以避免长时间阻塞浏览器。另一方面,如果 nextListItem
正在操纵 DOM,它比一次操作要慢得多。
一个例子:
var list = readHugeList();
var nextListItem = function() {
var item = list.pop();
if (item) {
setTimeout( nextListItem, 0);
// ^^^^^^^^ this line
}
};
setTimeout
的使用如何防止此处潜在的 Whosebug?我了解事件队列和堆栈的概念,但我很难将两者联系起来。
设置超时不会导致堆栈溢出,因为它是异步的。它只会将回调放入事件队列,而不会阻止执行。
第一种情况:
setTimeout 只是将回调放到事件队列中,父函数在不占用堆栈的情况下退出。
即使超时为0毫秒,也会在下一个事件循环中调用,因此不会阻塞执行中的代码
var nextListItem = function() {
var item = list.pop();
if (item) {
setTimeout( nextListItem, 0);
}
};
第二种情况:
父级调用子函数将新条目放入堆栈,即使父级未从堆栈中清除。
最终更多的递归调用会破坏堆栈。
var nextListItem = function() {
var item = list.pop();
if (item) {
nextListItem();
}
};
考虑 setTimeout(, 0)
在此函数终止后将函数安排到 运行。 nextListItem()
不会被递归调用,而是被JS环境再次调用
如果你这样做 var r() = function() { r(); };
函数会调用自身并溢出堆栈。如果您这样做 var r() = function() { setTimeout(r, 0); };
,那么 r()
将在 r()
终止后安排到 运行,并且它将永远 运行。
使用 setTimeout(, 0)
而不是 while
或 for
来遍历列表是有原因的:它允许浏览器在下一次调用 [= 之前处理其他事件19=]。如果列表很长,这可以避免长时间阻塞浏览器。另一方面,如果 nextListItem
正在操纵 DOM,它比一次操作要慢得多。