Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何预防你的node.js程序崩溃(译) #51

Open
TokenYangForever opened this issue Sep 21, 2018 · 0 comments
Open

如何预防你的node.js程序崩溃(译) #51

TokenYangForever opened this issue Sep 21, 2018 · 0 comments

Comments

@TokenYangForever
Copy link
Owner

  • 原文来自medium上的daily-js。原文地址。以下是翻译内容
  • 最近在面试node.js相关工作时问到两个问题,令我震惊的是几乎没有回答正确:
    • 当你在node中没有处理reject状态的promise时,会发生什么? 你该如何调试debug?
    • 在一个流中如果你没有处理错误error事件,会发生什么?

第一个问题 未处理的rejections

  • 在最新的node版本(8.X、9.X中),如果你有未处理的reject promise,控制台界面上会出现以下信息
(node:48446) UnhandledPromiseRejectionWarning: This is fine
(node:48446) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:48446) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
  • 这里有两条比较重要的信息:
    • 进程并没有崩溃。进程会继续工作,但是你已经收到了错误提醒。
    • 然而,在以后可能表现行为会改变。在未来的版本中,process进程会因此崩溃,并以非0的状态码退出
  • 接下来你可能想知道该如何正确地应对这种情况,你可能会想到把错误和栈跟踪信息发送到一个统计服务器上面,来收集错误信息。不用担心,nodeJs有提供一些办法。你可以监听由process触发的unhandledRejection事件:
process.on('unhandledRejection', (reason, promise) => {
  console.log('Unhandled Rejection:', reason)
  // 在这里处理
})
  • 在浏览器端也可以监听unhandledrejection事件,可以直接在window对象上添加监听器
window.addEventListener('unhandledrejection, '({
    reason
  }) => {
   // 在这里处理错误
  });
  • 监听的回调函数里面的reason参数就是reject返回的对象,比如Promise.reject(new Error('This is fine')),在回调函数里的reason就是那个error实例。所以在调用reject时,传递详细明确的错误类型或者信息进去是很重要的。
  • 你也可以监听process触发的warn事件,来获取关于未处理的rejections的信息。

第二个问题 steam中未处理的错误事件

  • 你可以尝试在你的node程序中写下如下代码:
const fs = require('fs')
const stream = fs.createReadStream('does-not-exist.txt')
  • 会发生什么?boom 你的程序会以一个非0的状态码崩溃。并且会打印出以下错误信息:
events.js:137
      throw er; // Unhandled 'error' event
      ^
Error: ENOENT: no such file or directory, open 'do-not-exists.txt'
  • 想象一下这种情景:有个用户上传一个文件给你的网站,在node服务端会以steam流来处理文件,因为它可能会很大,在传输过程中,用户关掉了程序,中断了过程。steam流意外的关闭了,如果没有错误处理的话,你的node程序直接崩溃了,所有用户都不能使用了。 所以要在所有处理stream流的地方,进行错误处理,来避免这种情况发生。

额外的炸弹: JSON.parse()

  • 这个看似无害的函数,当你传入一个不合法的JSON字符串时,也会抛出一个错误。使用它时一定要用try/catch包起来或者放入promise,在处理generator函数或者async函数时,也是同样的道理。不然的话,像如下代码就会杀掉你的程序:
app.get('/foo', (req, res, next) => {
  const foo = JSON.parse(req.body.jsonString)
  // ...
})
  • 记住:
    • 永远要处理promise的rejection,监听unhandledRejection事件只是做为处理rejection的最后一道防线,并协助debug以及收集错误报告。具体的每个promise都应该自行catch处理rejection。
    • 在处理stream流的时候,一定要处理错误。
    • 在处理*Sync() 函数以及JSON.parse()时,一定要用try/catch包起来或者放入promise中。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant