JS之异步异常处理

异步异常

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

[javascript]  view plain  copy
  1. var request = require('request');  
  2. var url = "http://xxxx.xxx.com/ssss/sss";  
  3.   
  4. try {  
  5.     request(url, function(error, response, body) {  
  6.         if (!error && response.statusCode == 200) {  
  7.             console.log(body)  
  8.         } else {  
  9.             throw new Error("Call WebService Error")  
  10.         }  
  11.     })  
  12. catch (e) {  
  13.     // 这里并不能捕获回调里面抛出的异常  
  14.     console.log("-----catch error------")  
  15.     console.log(e)  
  16. }  
运行后,发现当 request 失败后,异常并没有被 catch 捕获。然后差了下文档。发现 try-catch 只能捕获在其中执行的同步代码所抛出的异常。

[javascript]  view plain  copy
  1. try {  
  2.     // 同步代码  
  3. catch (e) {  
  4.     // 捕获同步异常  
  5. }  
显然上面的代码异步调用失败,异常并没有被捕获。实际使用中,我们需要捕获异步回调中的异常。怎么办?

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

Node

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

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

[javascript]  view plain  copy
  1. var request = require('request');  
  2.   
  3. process.on('uncaughtException'function (err) {  
  4.     console.log('---------catch--exception--------------');  
  5.     console.log(err);  
  6.     // process.exit(1);// 退出  
  7.     // server.close(function(){  
  8.     //  // todo   
  9.     // })  
  10. });  
  11.   
  12. var url = "http://xxxx.xxx.com/ssss/sss";  
  13. try {  
  14.     request(url, function(error, response, body) {  
  15.         if (!error && response.statusCode == 200) {  
  16.             console.log(body)  
  17.         } else {  
  18.             throw new Error("Call WebService Error")  
  19.         }  
  20.     })  
  21. catch (e) {  
  22.     // 这里并不能捕获回调里面抛出的异常  
  23.     console.log("-----catch error------")  
  24.     console.log(e)  
  25. }  

浏览器

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

[javascript]  view plain  copy
  1. // 在浏览器中  
  2. window.onerror = function(msg, file, line, col, error) {  
  3.   // todo process error  
  4. };  
例如:

[html]  view plain  copy
  1. <!DOCTYPE html>  
  2. <html>  
  3.   
  4. <head>  
  5. </head>  
  6.   
  7. <body>  
  8. <button onclick="afterclick()">Button</button>  
  9.     <script type="text/javascript">  
  10.         function afterclick() {  
  11.             throw new Error("My throw Error", "Throw error function");  
  12.         }  
  13.   
  14.         window.onerror = function(msg, file, line, col, error) {  
  15.           alert("Something error happen, please try again later!")  
  16.         };  
  17.     </script>  
  18. </body>  
  19.   
  20. </html>  
当点击按钮时,监听事件抛出异常,之后被捕获,浏览器弹出alert。

domain

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

[javascript]  view plain  copy
  1. var request = require('request');  
  2. var domain = require('domain');  
  3. var d = domain.create();  
  4. var url = "http://xxxx.xxx.com/ssss/sss";  
  5. d.run(function () {  
  6.     request(url, function(error, response, body) {  
  7.         if (!error && response.statusCode == 200) {  
  8.             console.log(body)  
  9.         } else {  
  10.             throw new Error("Call WebService Error")  
  11.         }  
  12.     })  
  13. });  
  14.   
  15. d.on('error'function (err) {  
  16.     console.log('Already catch err: ', err);  
  17. });  
通过对 error 时间监听,我们能捕获 run 函数里面发送的异常。

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

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

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

猜你喜欢

转载自blog.csdn.net/baidu_31333625/article/details/80298924