我最近遇到的文章来到尾部调用优化ECMAScript中6 。 我感兴趣的是测试TCO行为(即使我后来发现,该文章中提到的TCO不被支持的NodeJS 8+),发现行为我无法理解。
平原循环功能
'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');
此代码版本不停的运作。
综上所述:
- 纯循环功能:停在计数器10452和引发RangeError:最大调用堆栈大小超过
- 异步循环功能,无需任何函数内等待:停在计数器6967没有任何错误
- 在函数内等待异步循环功能:不停的运作
任何人都可以解释这种行为的差异或点我到任何关键字,我可以谷歌?