在奇怪的NodeJS观察无限循环函数执行(Strange observation on nodejs

2019-11-05 03:02发布

我最近遇到的文章来到尾部调用优化ECMAScript中6 。 我感兴趣的是测试TCO行为(即使我后来发现,该文章中提到的TCO不被支持的NodeJS 8+),发现行为我无法理解。

  1. 平原循环功能

     '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) 
  2. 没有任何异步循环函数的函数中等待

     '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 
  3. 与异步循环函数的函数中等待

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

    此代码版本不停的运作。

综上所述:

  1. 纯循环功能:停在计数器10452和引发RangeError:最大调用堆栈大小超过
  2. 异步循环功能,无需任何函数内等待:停在计数器6967没有任何错误
  3. 在函数内等待异步循环功能:不停的运作

任何人都可以解释这种行为的差异或点我到任何关键字,我可以谷歌?

文章来源: Strange observation on nodejs infinite loop function execution