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 ...
随机推荐
- 为实施了IFD的Dynamics 365更换自签名的SSL证书以符合Chrome的要求
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复259或者20170704可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...
- [TYVJ1728/BZOJ3224]普通平衡树-替罪羊树
Problem 普通平衡树 Solution 本题是裸的二叉平衡树.有很多种方法可以实现.这里打的是替罪羊树模板. 此题极其恶心. 前驱后继模块需要利用到rank模块来换一种思路求. 很多细节的地方容 ...
- 跨域访问之CORS
CORS:定义 2014年1月16日,W3C的Web应用工作组(Web Applications Working Group)和Web应用安全工作组(Web AppSec)联合发布了跨源资源共享(Cr ...
- STL—对象的构造与析构
STL内存空间的配置/释放与对象内容的构造/析构,是分开进行的. 对象的构造.析构 对象的构造由construct函数完成,该函数内部调用定位new运算符,在指定的内存位置构造对象 ...
- 一步一步学Vue(二)
接上篇,在本篇中,我们将要实现如下,功能,编辑和查询,我们当前的todolist程序,和线上其它的demo程序不同,我们会对其进行增删改查的基本操作,之后进行进一步的完善,按照常规的系统使用经验,一般 ...
- docker~linux下的部署和基本命令
回到目录 docker是最近比较流行的容器工具,它可以帮助我们快速部署应用,尤其是在“微服务”环境下,成百个服务要去启动,停止,部署一次太麻烦,而如果把它部署到docker里,下一次应用就方便多了,如 ...
- zoj 3963 heap partion
https://vjudge.net/problem/ZOJ-3963 题意: 给出一个数列,可以用这个数列构造一种二叉树,这个二叉树满足数的下标 i <= j,并且 si <= sj,s ...
- RxSwift 系列(四) -- Transforming Operators
前言 本篇文章将要学习RxSwift中四种转换操作符: map flatMap flatMapLatest scan map 通过使用一个闭包函数将原来的Observable序列转换为一个新的Obse ...
- java 读取文件的路径
1. 通用定位到用户目录下: String userDir = System.getProperty("user.dir"); 2. web项目定位到WEB-INF/class ...
- 天地图使用过程中由于display:none导致加载部分地图瓦片失败
在为按钮添加点击事件让地图显示的时候,初始加载未加载到当前页面尺寸的所有地图瓦片,在display:none之后停止加载地图,所以display:none属性去掉,改为dom解析完成之后$('#map ...