前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >第六十七期:Node中的栈追踪

第六十七期:Node中的栈追踪

作者头像
terrence386
发布2022-07-15 10:42:27
1.2K0
发布2022-07-15 10:42:27
举报
文章被收录于专栏:JavaScript高级程序设计

Node 中的栈追踪

当Node程序的执行出现错误时,发生错误的位置以及产生错误的方法会作为最终的输出内容记录到STDERR(标准错误输出)中。

这就是栈追踪。默认情况下,Node 的Javascript V8引擎保存10帧的记录。

但是,很多情况下,我们需要更多的帧数才能从堆栈上下文中找到产生错误的根本原因。另一方面,栈追踪越大,我们就需要消耗更多的CPU进程和内存,去保持栈追踪(stack trace)。

如何进行栈追踪

我们先简单搭建一个应用。

代码语言:javascript
复制
mkdir app
cd app & npm init -y & npm install express

进入app文件夹

代码语言:javascript
复制
touch index.js routes.js content.js

index.js文件中内容如下:

代码语言:javascript
复制
const express = require('express')
const routes = require('./routes')
const app = express()

app.use(routes)

app.listen(3000)

routes.js 中内容如下:

代码语言:javascript
复制
const content = require('./content')
const { Router } = require('express')

const router = new Router()

router.get('/', (req, res) => {
  res.send(content())
})

module.exports = router

content.js中内容如下:

代码语言:javascript
复制
function content(opts, c = 20) {
  return --c ? content(opts, c) : opts.ohoh
}
module.exports = content

然后我们启动程序:

代码语言:javascript
复制
node index.js

浏览器中打开localhost:3000,我们可以在终端窗口中看到栈追踪记录。

这个记录本质上是一个递归调用。

这个错误消息非常明显,【cannot read property 'ohoh' of undefined】。

但是因为我们的堆栈被限制为10帧,所以我们无法看到最初调用函数第一次迭代的内容。

通过使用 --stack-trace-limit 标识,我们可以解决这个问题。

代码语言:javascript
复制
node --stack-trace-limit=21 index.js

这时候,我们可以看到错误出现在app/routes.js的第7行第12列。

routes.js的第7行内容如下:

代码语言:javascript
复制
res.send(content())

调用content方法时参数为空,所以就报错了。

stack-trace-limit 标识是如何工作的

stack-trace-limit标识通知V8引擎在每个事件循环的tick中维护更多的stack,当程序出现错误时,生成一个可以回溯到最初调用函数的追踪栈。

然后我们就可以通过这个栈信息查找出现错误的原因。

但是...

我们可以在进程中设置堆栈限制吗?

如果我们希望在生产环境和开发环境中使用不同的堆栈跟踪限制呢?

我们可以跟踪同步函数调用吗?

有可能有更好看的堆栈跟踪吗?

开发环境中无限制的栈追踪

开发环境中,我们大多希望可以得到更多的上下文信息。

我们可以在index.js顶部添加一些内容:

代码语言:javascript
复制
if(process.env.NODE_ENV !== 'production'){
  Error.stackTraceLimit = Infinity
}

运行并访问程序

代码语言:javascript
复制
node index.js

这时候栈追踪的数量就没有限制了。

追踪栈的外观

我们可以把追踪栈的外观处理的更加人性化。

这需要我们安装cute-stack包。

代码语言:javascript
复制
npm install --save cute-stack

然后在index.js中引入它:

代码语言:javascript
复制
require('cute-stack')()

运行程序

代码语言:javascript
复制
node --stack-track-limit=21 index.js

然后我们可以看到格式化后的堆栈信息:

cute-stack利用了专有的API。Error.prepareStackTrace,它可以被指定为接收错误和堆栈输入的函数。然后,该函数可以处理堆栈并返回一个字符串。

异步栈追踪

JavaScript的异步特性会影响堆栈跟踪的工作方式。在JavaScript中,每个tick(每次JavaScript事件循环)都有一个新堆栈。

我们将content.js修改一下:

代码语言:javascript
复制
function content(opts, c = 20) {
  // return --c ? content(opts, c) : opts.ohoh
  function produce (cb){
    if(--c) setTimeout(produce,10,cb)
    cb(null,opts.ohoh)
  }
}
module.exports = content

同时修改下routes.js:

代码语言:javascript
复制
function content(opts, c = 20) {
  // return --c ? content(opts, c) : opts.ohoh
  function produce (cb){
    if(--c) setTimeout(produce,10,cb)
    cb(null,opts.ohoh)
  }
}
module.exports = content

然后运行程序。

我们可以看到按照超时时间降序排列的栈追踪信息。

我们可以通过【longjohn】模块获得异步栈追踪信息。

代码语言:javascript
复制
npm install --save-dev longjohn

然后修改index.js

代码语言:javascript
复制
// require('cute-stack')()
const express = require('express')
const routes = require('./routes')
const app = express()

if (process.env.NODE_ENV !== 'production') {
  // Error.stackTraceLimit = Infinity
  require('longjohn')
}

app.use(routes)

app.listen(3000)

运行程序。

这时候我们可以看到原始栈追踪的信息后面跟着一条虚线,虚线后面是之前的tick。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-02-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JavaScript高级程序设计 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 如何进行栈追踪
  • stack-trace-limit 标识是如何工作的
  • 但是...
  • 开发环境中无限制的栈追踪
  • 追踪栈的外观
  • 异步栈追踪
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档