`process.nextTick` 如何防止我的堆栈爆炸?
How does `process.nextTick` keep my stack from blowing up?
我偶然发现了一个写入文件的函数 (here on SO),但确保不会覆盖文件:
function writeFile(i){
var i = i || 0;
var fileName = 'a_' + i + '.jpg';
fs.exists(fileName, function (exists) {
if(exists){
writeFile(++i);
} else {
fs.writeFile(fileName);
}
});
}
现在下面有一个有趣的评论说:
Minor tweak: Since JavaScript doesn't optimize tail recursion away, change writefile(++i)
to process.nextTick(function(i) {writefile(++i);});
that will keep your stack from blowing up if you have to go through lots of file names.
请解释。 process.nextTick
如何防止堆栈爆炸?
更新:原来评论里的假设是错误的!无论如何,确实存在 process.nextTick
在防止堆栈溢出方面发挥作用的情况(请参阅接受的答案中的示例)。
如果你有一个同步调用自身的函数,比如 200k 次,代码将由于堆栈嵌套太深而错误退出。 process.nextTick
通过在每次迭代时清除调用堆栈来避免类似于 setTimeout(fn,0)
的方式。它只是将传递函数的执行推迟到下一次事件循环运行时。
更多阅读(但已过时):http://howtonode.org/understanding-process-next-tick
落入此陷阱的示例函数:
(function doWork (i) {
if (i === 0) return;
console.log('Doing work!');
doWork(--i);
}(2000000))
和用 process.nextTick 固定的相同功能:
(function doWork (i) {
if (i === 0) return;
console.log('Doing work!');
process.nextTick(function () {
doWork(--i);
});
}(2000000))
但是,在您的情况下,这不会成为问题,因为代码是异步的 fs.exists(
,因此您所指的评论是不正确的。
我偶然发现了一个写入文件的函数 (here on SO),但确保不会覆盖文件:
function writeFile(i){
var i = i || 0;
var fileName = 'a_' + i + '.jpg';
fs.exists(fileName, function (exists) {
if(exists){
writeFile(++i);
} else {
fs.writeFile(fileName);
}
});
}
现在下面有一个有趣的评论说:
Minor tweak: Since JavaScript doesn't optimize tail recursion away, change
writefile(++i)
toprocess.nextTick(function(i) {writefile(++i);});
that will keep your stack from blowing up if you have to go through lots of file names.
请解释。 process.nextTick
如何防止堆栈爆炸?
更新:原来评论里的假设是错误的!无论如何,确实存在 process.nextTick
在防止堆栈溢出方面发挥作用的情况(请参阅接受的答案中的示例)。
如果你有一个同步调用自身的函数,比如 200k 次,代码将由于堆栈嵌套太深而错误退出。 process.nextTick
通过在每次迭代时清除调用堆栈来避免类似于 setTimeout(fn,0)
的方式。它只是将传递函数的执行推迟到下一次事件循环运行时。
更多阅读(但已过时):http://howtonode.org/understanding-process-next-tick
落入此陷阱的示例函数:
(function doWork (i) {
if (i === 0) return;
console.log('Doing work!');
doWork(--i);
}(2000000))
和用 process.nextTick 固定的相同功能:
(function doWork (i) {
if (i === 0) return;
console.log('Doing work!');
process.nextTick(function () {
doWork(--i);
});
}(2000000))
但是,在您的情况下,这不会成为问题,因为代码是异步的 fs.exists(
,因此您所指的评论是不正确的。