我最近遇到了文章Tail call optimization in ECMAScript 6。我对测试TCO行为很感兴趣(尽管后来我发现文章提到的nodejs 8+不支持TCO),并且发现了我无法理解的行为。
普通循环功能
'use strict';
process.on('SIGTERM', () =>
{
console.log('SIGTERM received');
process.exit(0);
})
process.on('SIGINT', () =>
{
console.log('SIGINT received');
process.exit(0);
})
process.on('uncaughtException', (error) =>
{
console.error('Uncaught exception', error);
process.exit(1);
})
process.on('unhandledRejection', (error) =>
{
console.error('Unhandled rejection', error);
process.exit(0);
})
let counter = 0;
function test()
{
console.log(`Counter: ${counter++}`);
test();
}
console.log('Test started');
test();
console.log('Test ended');
此版本的代码产生:
Test started
Counter: 0
...
Counter: 10452
Uncaught exception RangeError: Maximum call stack size exceeded
at WriteStream.removeListener (events.js:306:28)
at write (console.js:130:12)
at Console.log (console.js:135:3)
at test (/test.js:31:13)
at test (/test.js:32:5)
at test (/test.js:32:5)
at test (/test.js:32:5)
at test (/test.js:32:5)
at test (/test.js:32:5)
at test (/test.js:32:5)
at test (/test.js:32:5)
at test (/test.js:32:5)
at test (/test.js:32:5)
at test (/test.js:32:5)
at test (/test.js:32:5)
at test (/test.js:32:5)
异步循环功能,功能内无任何等待
'use strict';
process.on('SIGTERM', () =>
{
console.log('SIGTERM received');
process.exit(0);
})
process.on('SIGINT', () =>
{
console.log('SIGINT received');
process.exit(0);
})
process.on('uncaughtException', (error) =>
{
console.error('Uncaught exception', error);
process.exit(1);
})
process.on('unhandledRejection', (error) =>
{
console.error('Unhandled rejection', error);
process.exit(0);
})
let counter = 0;
async function test()
{
console.log(`Counter: ${counter++}`);
test();
}
console.log('Test started');
test();
console.log('Test ended');
此版本的代码产生:
Test started
Counter: 0
...
Counter: 6967
Test ended
异步循环功能,该功能在功能内处于等待状态
'use strict';
const bluebird = require('bluebird');
process.on('SIGTERM', () =>
{
console.log('SIGTERM received');
process.exit(0);
})
process.on('SIGINT', () =>
{
console.log('SIGINT received');
process.exit(0);
})
process.on('uncaughtException', (error) =>
{
console.error('Uncaught exception', error);
process.exit(1);
})
process.on('unhandledRejection', (error) =>
{
console.error('Unhandled rejection', error);
process.exit(0);
})
let counter = 0;
async function test()
{
await bluebird.delay(1);
console.log(`Counter: ${counter++}`);
test();
}
console.log('Test started');
test();
console.log('Test ended');
此版本的代码不间断运行。
摘要:
有人能解释这种行为差异或将我指向可以谷歌搜索的任何关键字吗?