Node.js之错误处理
Node.js之错误处理
1. 使用 domain 模块处理错误
try..catch
多用于捕捉同步方法中的抛出错误,但不能用try..catch捕捉异步方法中抛出de错误
如:
1 var http = require('http')
2 try{
3 http.createServer(function(req,res){
4 if(req.url!="/favicon.ico"){
5 noneexist();//不存在本函数
6 res.writeHead(200,{'Content-Type':'text/html'})
7 res.write('<head><meta charset="utf-8"/></head>')
8 res.end('你好\n')
9 }
10 }).listen(8000,"127.0.0.1")
11 }
12 catch(err){
13 console.log('接收客户端请求时发生以下错误:')
14 console.log(err.code)
15 }
在用浏览器请求时,会出错,因为noneexist()不存在,程序也会停止运行
$ node app.js
D:\Users\yuan\Desktop\app.js:6
noneexist();//不存在本函数
^
ReferenceError: noneexist is not defined
at Server.<anonymous> (D:\Users\yuan\Desktop\app.js:6:13)
at emitTwo (events.js:125:13)
at Server.emit (events.js:213:7)
at parserOnIncoming (_http_server.js:602:12)
at HTTPParser.parserOnHeadersComplete (_http_common.js:116:23)
为了防止程序被强制关闭,提供了一个uncaughtException事件,用于捕捉及处理任何未被处理的错误
可将代码改成如下形式:
var http = require('http')
var http = require('http')
http.createServer(function(req,res){
if(req.url!="/favicon.ico"){
noneexist();//不存在本函数
res.writeHead(200,{'Content-Type':'text/html'})
res.write('<head><meta charset="utf-8"/></head>')
res.end('你好\n')
}
}).listen(8000,"127.0.0.1")
process.on('uncaughtException',function(err){
console.log('接收客户端请求时发生以下错误:')
console.log(err)
})
运行结果如下会报错,但不会停止:
$ node app.js
接收客户端请求时发生以下错误:
ReferenceError: noneexist is not defined
at Server.<anonymous> (D:\Users\yuan\Desktop\app.js:6:13)
at emitTwo (events.js:125:13)
at Server.emit (events.js:213:7)
at parserOnIncoming (_http_server.js:602:12)
at HTTPParser.parserOnHeadersComplete (_http_common.js:116:23)
|
但这种方法可能会出现资源泄露,因此利用domain模块进行处理错误,代码如下:
var http = require('http')
var domain = require('domain')
http.createServer(function(req,res){
var d = domain.create()
d.once('error',function(err){
res.writeHead(200,{'Content-Type':'text/html'})
res.write('<head><meta charset="utf-8"/></head>')
res.write('服务器接收客户端请求时发生以下错误: ')
res.end(err.message)
})
d.run(function(){
if(req.url!=="/favicon.ico"){
nonexist();
res.writeHead(200,{'Content-Type':'text/html'})
res.write('<head><meta charset="utf-8"/></head>')
res.end('你好\n')
}
})
}).listen(8000,"127.0.0.1")
浏览器访问后在浏览器中会出现错误信息,程序不会间断
下面详细介绍Domain
2. 创建并使用Domain
创建domain对象:
var domain= domain.create();
当该对象捕获到任何错误信息时,触发该对象的error事件,可以通过对监听对象的error事件并指定事件回调函数的方法来实现对捕捉到错误时的处理。
domain.on('error',function(err){
//事件回调函数代码
})
在domain对象中定义了一个name属性值,用于获取Domain对象的名字
domain。name
Domain对象被创建后,利用run方法指定Domain监视对象
domain。run(fn)//fn为一函数
eg:
var domain = require('domain')
var fs = require('fs')
var d = domain.create()
d.name = 'dl'
d.on('error',function(err){
console.error(d.name,err)
})
d.run(function(){
process.nextTick(function(){
setTimeout(function(){
fs.open('non-existent file','r',function(err,fd){
if(err)throw err
})
},1000)
})
})
输出结果为:
$ node app.js
dl { Error: ENOENT: no such file or directory, open 'D:\Users\yuan\Desktop \non-existent file'
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path: 'D:\\Users\\yuan\\Desktop\\non-existent file',
domain:
Domain {
domain: null,
_events: { error: [Function] },
_eventsCount: 1,
_maxListeners: undefined,
members: [],
name: 'dl' },
domainThrown: true }
3. 隐式绑定与显示绑定
当使用Domain对象的run方法指定所有监听的函数时,函数中使用的实例对象都隐式地绑定到Domain对象上。有时需要某些对象不绑定Domain上,或者绑定到另一个Domain上,因此需要显性绑定,利用add方法
domain.add(emitter)
可通过下面例子说明,我们创建一个Http服务器,并指定服务器接收到的客户端请求时,首先创建一个Domain对象,然后使用该对象的add方法分别将用于读取客户端请求数据的http.IncomingMessage对象,与用于发送服务器端响应数据的http.ServerRespanse对象绑定到Domain对象上,并制定当Domain对象那个捕获到错误时客户端返回错误信息。
1 var http = require('http')
2 var domain = require('domain')
3 http.createServer(function(req,res){
4 var d = domain.create();
5 d.add(req)
6 d.add(res)
7 d.on('error',function(err){
8
9 res.writeHead(200)
10 res.write('服务器接收客户端请求时发生以下错误: ')
11 res.end(err.message)
12
13 })
14
15 res.writeHead(200)
16 req.on('data',function(){
17 bibeexists();
18 res.write('你好')
19 res.end()
20 })
21
22 }).listen(8000)
接下来创建一个用于向Http服务器提供请求的模块文件代码
1 var http = require('http')
2 var options = {
3 hostname:'localhost',
4 port:8888,
5 path:'/',
6 method:'POST'
7 }
8 var req = http.request(options,function(res){
9 res.setEncoding('utf8')
10 res.on('data',function(chunk){
11 console.log('响应内容:' + chunk)
12 })
13 })
14 req.write('你好')
15 req.end('再见')
分别在不同界面运行以上两个程序,可得,服务器不停止工作,http请求端返回错误数据:
[root@kuber2 webproject]# node client.js
响应内容:服务器接收客户端请求时发生以下错误:
响应内容:noneexists is not defined
[root@kuber2 webproject]#
使用了add方法绑定了Domain,可以使用remove方法解绑,即
domain.remove(emitter)
4 绑定回调函数与拦截回调函数
可以利用bind方法将一个回调函数与Domain绑定在一起
domain.bind(callback)
回调函数中如果有异常将异常抛出给domain,但本方法必须有throw err
eg:
1 var fs = require('fs')
2 var domain = require('domain')
3 var d = domain.create()
4 fs.readFile('./test.txt',d.bind(function(err,data){
5 if(err) {
6
7 console.log('blind绑定的回调函数抛出的异常:' + err.message)
8 throw err
9 }
10 else console.log(data)
11 })
12 )
13 d.on('error',function(err){
14 console.log('读取文件时发生以下错误:')
15 console.log(err)
16 })
运行所得结果如下:
blind绑定的回调函数抛出的异常:ENOENT: no such file or directory, open './test.txt'
读取文件时发生以下错误:
{ Error: ENOENT: no such file or directory, open './test.txt'
at Error (native)
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: './test.txt',
domain:
Domain {
domain: null,
_events: { error: [Function] },
_eventsCount: 1,
_maxListeners: undefined,
members: [] },
domainThrown: true }
[root@kuber2 webproject]#
使用intercept可以拦截回调函数的异常,使用方法:
domain.intercept(callback)
eg:
1 var fs = require('fs')
2 var domain = require('domain')
3 var d = domain.create()
4 fs.readFile('./test.txt',d.intercept(function(err,data){
5 console.log(data)
6 })
7 )
8 d.on('error',function(err){
9 console.log('读取文件时发生以下错误:')
10 console.log(err)
11 })
运行结果:
[root@kuber2 webproject]# node app1.js
读取文件时发生以下错误:
{ Error: ENOENT: no such file or directory, open './test.txt'
at Error (native)
errno: -2,
code: 'ENOENT',
syscall: 'open',
path: './test.txt',
domain:
Domain {
domain: null,
_events: { error: [Function] },
_eventsCount: 1,
_maxListeners: undefined,
members: [] },
domainThrown: false,
domainBound: [Function] }
[root@kuber2 webproject]#
5 domain堆栈的弹出与推入
当使用run,bind,intercept方法监听函数时,将把Domain对象推入domai堆栈中,可利用_stack属性查看Domain堆栈内容,堆栈中只能存放一个对象,后这会将前者挤出堆栈。
利用下列代码进行说明:
1 var domain = require('domain')
2 var d1 = domain.create();
3 d1.name = "d1"
4 var d2 = domain.create();
5 d2.name = 'd2'
6 console.log('原始堆栈:')
7 console.log(domain._stack)
8 d1.run(function(){
9 console.log('d1对象:')
10 console.log(d1)
11 console.log('运行d1对象后的堆栈内容:')
12 console.log(domain._stack)
13 })
14 d2.run(function(){
15 console.log('d2对象:')
16 console.log(d2)
17 console.log('运行d2对象后的堆栈内容:')
18 console.log(domain._stack)
19 })
执行结果如下:
[root@kuber2 webproject]# node app2.js
原始堆栈:
[]
d1对象:
Domain {
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
members: [],
name: 'd1' }
运行d1对象后的堆栈内容:
[ Domain {
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
members: [],
name: 'd1' } ]
d2对象:
Domain {
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
members: [],
name: 'd2' }
运行d2对象后的堆栈内容:
[ Domain {
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
members: [],
name: 'd2' } ]
[root@kuber2 webproject]#
可以利用exit方法将Domain对象从domain堆栈中弹出,弹出后不能再捕获错误
eg:
1 var domain = require('domain')
2 var d = domain.create()
3 d.on('error',function(err){
4 console.log('Domain对象捕获到错误')
5 })
6 console.log('原始堆栈:')
7 console.log(domain._stack)
8 d.run(function(){
9 console.log('运行domain对象后的堆栈内容:')
10 console.log(domain._stack)
11 throw new Error("error")
12 })
此时输出结果为:
[root@kuber2 webproject]# node app3.js
原始堆栈:
[]
运行domain对象后的堆栈内容:
[ Domain {
domain: null,
_events: { error: [Function] },
_eventsCount: 1,
_maxListeners: undefined,
members: [] } ]
Domain对象捕获到错误
[root@kuber2 webproject]#
将domain对象从堆栈中弹出:
1 var domain = require('domain')
2 var d = domain.create()
3 d.on('error',function(err){
4 console.log('Domain对象捕获到错误')
5 })
6 console.log('原始堆栈:')
7 console.log(domain._stack)
8 d.run(function(){
9 d.exit();
10 console.log('运行domain对象后的堆栈内容:')
11 console.log(domain._stack)
12 // throw new Error("error")
13 })
14
输出结果为:
[root@kuber2 webproject]# node app3.js
原始堆栈:
[]
运行domain对象后的堆栈内容:
[]
domain对象中抛出异常会是程序停止:
1 var domain = require('domain')
2 var d = domain.create()
3 d.on('error',function(err){
4 console.log('Domain对象捕获到错误')
5 })
6 console.log('原始堆栈:')
7 console.log(domain._stack)
8 d.run(function(){
9 d.exit();
10 console.log('运行domain对象后的堆栈内容:')
11 console.log(domain._stack)
12 throw new Error("error")
13 })
14
输出结果从,程序停止:
/root/webproject/app3.js:12
throw new Error("error")
^
Error: error
at Domain.<anonymous> (/root/webproject/app3.js:12:8)
at Domain.run (domain.js:221:14)
at Object.<anonymous> (/root/webproject/app3.js:8:3)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.runMain (module.js:604:10)
at run (bootstrap_node.js:389:7)
[root@kuber2 webproject]#
可以使用Domain对象的enter方法将一个Domain对象推入domain堆栈中并使该Domain对象变成当前使用的Domain对象
继续修改上述代码加入enter方法:
1 var domain = require('domain')
2 var d = domain.create()
3 d.on('error',function(err){
4 console.log('Domain对象捕获到错误')
5 })
6 console.log('原始堆栈:')
7 console.log(domain._stack)
8 d.run(function(){
9 d.exit();
10 console.log('运行domain对象后的堆栈内容:')
11 console.log(domain._stack)
12 d.enter()
13 console.log('运行enter方法后的堆栈内容:')
14 console.log(domain._stack)
15 throw new Error("error")
16 })
17
运行结果:
root@kuber2 webproject]# node app3.js
原始堆栈:
[]
运行domain对象后的堆栈内容:
[]
运行enter方法后的堆栈内容:
[ Domain {
domain: null,
_events: { error: [Function] },
_eventsCount: 1,
_maxListeners: undefined,
members: [] } ]
Domain对象捕获到错误
[root@kuber2 webproject]#
如果多个Domain对象存在嵌套,则会抛出最内层的异常。如果外层用exit方法弹出,则虽有的Domain对象都会被弹出
6. Domain对象的销毁
在一个Domain对象不再使用时,可对其进行销毁
d.dispose()
Node.js之错误处理的更多相关文章
- Node.js之错误处理与断言处理
Node.js之错误处理与断言处理 1. 使用 domain 模块处理错误 try..catch 多用于捕捉同步方法中的抛出错误,但不能用try..catch捕捉异步方法中抛出de错误 如: 1 va ...
- Node.js ECONNREFUSED错误
1 现象 node服务器 遇见此错误,如下:events.js:71throw arguments[1]; // Unhandled 'error' event^Error: connect ECON ...
- node.js 标准/错误输出 和 process.exit
node.js中,各种模块有一种标准的写法: this._process.exec(command, options, function (err, stdout, stderr) { callbac ...
- node.js开发错误——DeprecationWarning: Mongoose: mpromise
原文地址 使用mongoose进行数据库操作时,总是提示: (node:5684) DeprecationWarning: Mongoose: mpromise (mongoose's default ...
- node.js常见错误及解决办法
1.npm express命令行下不能执行 解决办法: 4版本需要安装express-generatorc才能使用express命令npm install -g express-generatorwh ...
- 73.node.js开发错误——TypeError: Cannot set property 'XXX' of undefined
转自:https://blog.csdn.net/fd214333890/article/details/53467429
- 61.node.js开发错误——Error: Connection strategy not found
转自:https://blog.csdn.net/fd214333890/article/details/53457145
- Fundebug上线Node.js错误监控啦
作为全栈JavaScript错误实时监测平台,Fundebug的Node.js实时错误监测服务上线啦,我们能够帮助开发者及时,高效地发现并且解决Node.js错误,从而提高开发效率,并提升用户体验. ...
- Node.js log2: ERR when execute command >npm install
1.Node.js创建项目 项目microblog创建成功,提示:cd microblog& npm install 项目创建完成时的目录如下图所示: 2.Node.js错误 如题所言: E ...
随机推荐
- Cisco VPP(1) 简单介绍
一.简单介绍 VPP全称Vector Packet Processing.是Cisco2002年开发的商用代码. 2016年2月11号,Linux基金会创建FD.io项目.Cisco将VPP代码的开源 ...
- Codeforces Round #313 A. Currency System in Geraldion(简单题)
A. Currency System in Geraldion time limit per test 2 seconds memory limit per test 256 megabytes in ...
- ASP.NET无法检测IE10浏览器,导致无法登录
今天发现在IE10中打开我开发的网站时,无法登入,页面总会自动重新退出到登录页,后经上网查资料发现这是ASP.NET 2.0.3.5和4.0的Bugs,因这些版本的.NET Framework无法识别 ...
- 浅谈JVM内存模型
JAVA虚拟机在执行JAVA程序的时候,会把它管理的内存分成若干不同的数据区域,每个区域都有各自的用途.目前大致把JVM内存模型划分为五个区域:程序计数器,虚拟机栈,本地方法栈,堆和方法区. 程序计数 ...
- SpringMVC+MyBaties关于上传(跟新)图片的问题
/** * 方法名:uploadPhoto * 描 述:TODO(上传图片) * 作 者:池彦龙 * 时 间:2017/03/30 * 返回类型: * 参 数: * 异 常: */ Controlle ...
- 那些有意思的Github
https://github.com/ngosang/trackerslist Linux下那些有趣的命令.. https://www.linu&xp&robe.com/linux-i ...
- HTTP Status 500 - Could not write content: could not initialize proxy - no Session
分析出现no Session错误的原因以及给出解决方案: 使用SpringMVC + JSON数据返回时,经常会出现no Session的错误: 报错原因:因为懒加载在提取关联对象的属性值的时候发现E ...
- datatable 的使用方法
遍历datatable的方法 +方法一:DataTable dt = dataSet.Tables[0];for(int i = 0 ; i < dt.Rows.Count ; i++){str ...
- sigar的使用
与普通jar包不同,Sigar API还要依赖本地的库文件来进行工作,其中: Windows下Sigar.jar 依赖:sigar-amd64-winnt.dll 或 sigar-x86-winnt. ...
- 吝啬的国度 ---用vector 来构图
根据题目可以看出来 有n 个城市 只有 n-1 条路线 那么 就可以确定这个图中 不存在 圆 所以从一个点到另一个点 只有一条唯一的路 所以从一个节点到另一个节点 那么 这个节点只有一个唯 ...