javascript - `process.nextTick` 如何防止我的堆栈崩溃?

标签 javascript node.js recursion stack-overflow tail-recursion

我偶然发现了一个函数( 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(,代码是异步的,因此您引用的注释是不正确的。

关于javascript - `process.nextTick` 如何防止我的堆栈崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28349548/

相关文章:

c++ - 二叉搜索树递归删除

c++ - 在 C++ 中递归地总结链表中的元素

javascript - 如何使 Surface 大小适合文本内容

node.js - 是否有任何快速工具可以在不删除 JavaScript 源代码注释的情况下执行常量替换?

mysql - 从 node-mysql 连接到 Amazon RDS (MySQL) 时出错

node.js - Node.js 事件循环的概念与 CICS 伪对话式编程相同吗?

algorithm - 帕斯卡三角 Scala : Compute elements of Pascal's triangle using tail recursive approach

具有 0 延迟问题的 Javascript setTimeout

javascript - react : Use this. props.children 或将组件作为命名 Prop 传递

javascript - HighChart中导出的多个图表与屏幕上显示的不一样