JS之异步异常处理

异步异常

最近用request call 一个webservice 做个测试。代码如下,request 函数被 try-catch 包括着,这样当失败时打印一些log。这里没有使用 Promise。

var request = require('request');
var url = "http://xxxx.xxx.com/ssss/sss";

try {
	request(url, function(error, response, body) {
		if (!error && response.statusCode == 200) {
            console.log(body)
        } else {
        	throw new Error("Call WebService Error")
        }
	})
} catch (e) {
	// 这里并不能捕获回调里面抛出的异常
	console.log("-----catch error------")
	console.log(e)
}
运行后,发现当 request 失败后,异常并没有被 catch 捕获。然后差了下文档。发现 try-catch 只能捕获在其中执行的同步代码所抛出的异常。

try {
	// 同步代码
} catch (e) {
	// 捕获同步异常
}
显然上面的代码异步调用失败,异常并没有被捕获。实际使用中,我们需要捕获异步回调中的异常。怎么办?

之后查看一些文档发现 无论是Node中 还是浏览器环境中,都提供了对捕获这类异常的支持。下面来看一下:

Node

在我们的代码中添加下面一段代码。

process.on('uncaughtException', function (err) {
	// todo
});
注意,这段代码一定要加在最前面。否则它 catch 不到。例如:

var request = require('request');

process.on('uncaughtException', function (err) {
	console.log('---------catch--exception--------------');
	console.log(err);
	// process.exit(1);// 退出
	// server.close(function(){
	// 	// todo 
	// })
});

var url = "http://xxxx.xxx.com/ssss/sss";
try {
	request(url, function(error, response, body) {
		if (!error && response.statusCode == 200) {
            console.log(body)
        } else {
        	throw new Error("Call WebService Error")
        }
	})
} catch (e) {
	// 这里并不能捕获回调里面抛出的异常
	console.log("-----catch error------")
	console.log(e)
}

浏览器

在浏览器中,很多时候出现Error,整个页面就挂掉了。相反,如果我们能catch 这些Error,然后弹出一些友好界面会有更好的体验。在window对象下有个 onerror 属性。

// 在浏览器中
window.onerror = function(msg, file, line, col, error) {
  // todo process error
};
例如:

<!DOCTYPE html>
<html>

<head>
</head>

<body>
<button οnclick="afterclick()">Button</button>
    <script type="text/javascript">
        function afterclick() {
            throw new Error("My throw Error", "Throw error function");
        }

        window.onerror = function(msg, file, line, col, error) {
          alert("Something error happen, please try again later!")
        };
    </script>
</body>

</html>
当点击按钮时,监听事件抛出异常,之后被捕获,浏览器弹出alert。

domain

从上面两点可以发现,如果可以通过某种方式来捕获回调函数中的异常,那么就不会有 uncaughtException 错误导致的崩溃。对此,Node 提供了一个很有用的模块- domain模块,它可以用来捕获回调函数中抛出的异常。官方文档
domain 主要有两个api 函数,run 和 error 事件。即 run里面执行出现的异常都能被 error 时间捕获。例如:

var request = require('request');
var domain = require('domain');
var d = domain.create();
var url = "http://xxxx.xxx.com/ssss/sss";
d.run(function () {
    request(url, function(error, response, body) {
		if (!error && response.statusCode == 200) {
            console.log(body)
        } else {
        	throw new Error("Call WebService Error")
        }
	})
});

d.on('error', function (err) {
    console.log('Already catch err: ', err);
});
通过对 error 时间监听,我们能捕获 run 函数里面发送的异常。

到了这里,你可能觉得很完美了。可惜的是,domain 也有个问题,它并不能捕获所有的异步异常。这里有个社区的帖子,讲解的很很详细。

http://cnodejs.org/topic/516b64596d38277306407936

因此,好的做法是 domain + uncaughtException。








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值