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 var htt ...
- 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 ...
随机推荐
- 关于非阻塞connnect的看法
关于非阻塞connnect的总结 在面试题中,看到有关于阻塞connect和非阻塞connect的区别: 显然,我们可以从阻塞和非阻塞的意思来回答,既然是阻塞,那么执行connect的操作会一直阻塞到 ...
- 从 RequireJs 源码剖析脚本加载原理
引言 俗话说的好,不喜欢研究原理的程序员不是好的程序员,不喜欢读源码的程序员不是好的 jser.这两天看到了有关前端模块化的问题,才发现 JavaScript 社区为了前端工程化真是煞费苦心.今天研究 ...
- jsoncpp动态解析节点类型
在互联网无处不在的今天,JSON作为轻量级数据存储格式,被广泛应用到互联网数据传输中.众所周知,JSON由键/值对.对象.数组组成,其中键/值对的值包括以下几种类型: enum ValueType { ...
- mybaits错误解决:There is no getter for property named 'parentId ' in class 'java.lang.String'
在使用mybaitis传参数的时候,如果仅传入一个类型为String的参数,那么在 xml文件中应该使用_parameter来代替参数名. 比如mapper中如下方法,只有一个String值 publ ...
- Actor模型原理
1.Actor模型 在使用Java进行并发编程时需要特别的关注锁和内存原子性等一系列线程问题,而Actor模型内部的状态由它自己维护即它内部数据只能由它自己修改(通过消息传递来进行状态修改),所以使用 ...
- 二.GC相关之Java内存模型
根据上节描述的问题,我们知道其最终原因是GC导致的.本节我们就先详细探讨下与GC息息相关的Java内存模型. 名词解释:变量,理解为java的基本类型.对象,理解为java new出来的实例. Jav ...
- C++ STL 优先队列详解
一.解释: 优先队列是队列的一种,不过它可以按照自定义的一种方式(数据的优先级)来对队列中的数据进行动态的排序,每次的push和pop操作,队列都会动态的调整,以达到我们预期的方式来存储. 例如,将元 ...
- centos下编译安装Openssl
yum install -y zlib*mkdir /datacd /data下载好tar包tar zxf openssl-1.0.2g.tar.gzcd openssl-1.0.2g./config ...
- HH去散步[SDOI2009]
题目描述 HH有个一成不变的习惯,喜欢饭后百步走.所谓百步走,就是散步,就是在一定的时间 内,走过一定的距离. 但是同时HH又是个喜欢变化的人,所以他不会立刻沿着刚刚走来的路走回. 又因为HH是个喜欢 ...
- zabbix_server----邮箱报警
zabbix邮件报警部署!!!!!!!!!!!!!!! Zabbix监控服务端.客户端都已经部署完成,被监控主机已经添加,Zabiix监控运行正常,通过查看Zabbix监控服务器,可以了解服务器的运行 ...