How does `process.nextTick` keep my stack from blowing up?

I've stubled upon a function (here on SO) which writes a file, but makes sure to not overwrite a file:

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

Now there is an interesting comment below which says:

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.

Please explain. How does process.nextTick prevent the stack from blowing up?


Update: Turns out the assumption in the comment was wrong! Anyway, cases do exist where process.nextTick plays a role in preventing a stack overflow (see examples in accepted answer).

Answers:

Answer

If you had a function that called itself synchronously, say, 200k times, the code will exit with error due to the stack being too deeply nested. process.nextTick avoids that similar to the way setTimeout(fn,0) will by clearing the callstack on each iteration. It simply defers the execution of the passed function until the next time the eventloop runs.

More reading (but out of date): http://howtonode.org/understanding-process-next-tick

Example function that would fall into this trap:

(function doWork (i) {
    if (i === 0) return;
    console.log('Doing work!');
    doWork(--i);
}(2000000))

and the same function fixed with process.nextTick:

(function doWork (i) {
  if (i === 0) return;
  console.log('Doing work!');
  process.nextTick(function () {
    doWork(--i);
  });
}(2000000))

However, in your case this won't be a problem because the code is asynchronous due to fs.exists(, therefore the comment you were referring to is incorrect.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.