错误处理(异常处理)
我们都知道,node
应用程序是运行在一个单线程,单进程的环境当中的,这也就意味着只要成勋在运行过程中出现一个错误,整个服务器就会崩溃,查看下面的代码:
const http = require ('http' ) const server = http.createServer ((req,res )=> { if (req.url === '/data' ){ throw new Error ('丢出一个错误!!!' ) } res.end ('服务器正常运行!' ) }) server.listen (3000 ,()=> { console .log ('服务器已启动,3000端口正在监听...' ); })
结果展示:
当我们调用'/list'
接口时,数据成功返回,服务器也能正常运行
当我们调用'/data'
接口时,数据不能正常返回且服务器也发生了报错,导致整个服务器崩溃
由此可见,要想搭建一个健壮的node
服务器,就需要捕获该服务器可能发生的每一个异常错误,这一点在node
开发中非常的重要,由此引出node
中的异常捕获!
在Node
中的异常捕获以及处理
首先我们可以将node
中的代码非为两类,一类是同步代码
,另一类则是异步代码
,同步代码的异常处理还是非常简单的,我么直接将同步代码
放进try..catch
中即可,而异步代码就需要使用promise
或者async/await
使用try...catch
捕获同步代码的异常 const http = require ('http' ) const server = http.createServer ((req,res )=> { try { if (req.url === '/data' ){ throw new Error ('丢出一个错误!!!' ) } res.end ('服务器正常运行!' ) } catch (error) { console .log ('错误信息:' ,error); res.end ('请求失败!请稍后重试..' ) } }) server.listen (3000 ,()=> { console .log ('服务器已启动,3000端口正在监听...' ); })
结果展示
由上图我们可以看出,即便第一个接口请求出错了,整个服务器也不会崩溃,其他接口也能正常响应!
使用promise
以及async/await
捕获异步代码的异常
const http = require ('http' ) const server = http.createServer ((req,res )=> { new Promise (()=> { if (req.url === '/data' ){ throw new Error ('丢出一个错误!!!' ) } res.end ('服务器正常运行!' ) }).catch ((err )=> { console .log ('错误信息:' ,err); res.end ('请求失败,请稍后重试...' ) }) }) server.listen (3000 ,()=> { console .log ('服务器已启动,3000端口正在监听...' ); })
const http = require ('http' ) const server = http.createServer (async (req,res)=>{ try { await new Promise (()=> { if (req.url === '/data' ){ throw new Error ('丢出一个错误!!!' ) } res.end ('服务器正常运行!' ) }) } catch (error) { console .log ('错误信息:' ,error); res.end ('请求失败,请稍后重试...' ) } }) server.listen (3000 ,()=> { console .log ('服务器已启动,3000端口正在监听...' ); })
结果均如上面的动图所示
全局异常捕获(process.on('uncaughtException')
)
这种方案可以监听全局的异常并处理,就可以避免了又一场未被捕获的情况出现导致整个应用程序崩溃,这种方案可以认为是万能的,但是实用性很差,因为如果一个错误没有被及时捕获,任由其冒泡并最终有process
来处理,那么此时抛出的这个异常的上下文信息就已经丢失了,缺少诸如req,res
等对象,我们就无法对客户端发出一个积极的响应,用户只能等待请求超时,这是一个非常不好的用户体验,因此这只能作为一个兜底的方案.
const http = require ('http' ) process.on ('uncaughtException' ,(error )=> { console .log ('全局process捕获的异常信息:' ,error); }) const server = http.createServer (async (req,res)=>{ if (req.url === '/data' ){ throw new Error ('丢出一个错误!!!' ) } res.end ('服务器正常运行!' ) }) server.listen (3000 ,()=> { console .log ('服务器已启动,3000端口正在监听...' ); })
以上提到的均为node
原生的异常捕获以及处理, 使用框架则另需额外学习(框架应该有自带的错误捕获)
Crypto
(加密模块)
官方文档
crypto
模块的目的是为了提供通用的加密和哈希算法。用纯JavaScript
代码实现这些功能不是不可能, 但速度会非常慢。Nodejs
用C/C++
实现这些算法后,通过cypto
这个模块暴露为JavaScript
接口,这样用 起来方便,运行速度也快。
加密模块的使用场景也非常的多,例如我们搭建后台将用户数据加密保存到数据库中,这样的话即便别人拿到了你的数据库,也是获取到一堆没有用的加密信息
MD5
加密算法
这种算法是不可逆的,也就是说你使用它进行一些数据的加密后获得到的加密数据是无法转回来来的数据,这种一般用于用户的隐私信息保存,如密码,使用场景如下:你可以使用MD5
算法将用户的密码经过加密后保存到数据库中,最后用户的每一次登录提交过来的密码再进行一次MD5
的数据加密,如果两者一致证明登录校验成功.
const crypto = require ('crypto' ) const hash = crypto.createHash ('md5' ) hash.update ('Hello World!' ) hash.update ('lam' ) console .log ( '加密后的数据输出:(16进制或者base64):' , hash.digest ('base64' ), );
SHA1
密钥算法
上面提到的md5
这种加密算法还不算非常的安全,因为它是随机的,意味着你也不知道你传进去的数据会生成什么,这也就导致了别人一样可以通过撞
的方式来获取你的原始数据(彩虹表了解一下
),下面介绍这种SHA1
算法它可以让你自定义设置一个密码,去生成不一样的加密数据,这就可以让用户有多种选择,不一样的数据类型我可以设置不一样的密钥去加密
const crypto = require ('crypto' ) const hash = crypto.createHmac ('sha1' ,'secret-key' ) hash.update ('Hello World!' ) hash.update ('lam' ) console .log ( '加密后的数据输出:(16进制或者base64):' , hash.digest ('hex' ), );
对称加密算法
对称加密算法下面讲讲AES``,AES
是一种常用的对称加密算法,加解密都用同一个密钥。crypto
模块提供了AES
支持,但是需要自己 封装好函数
const crypto = require ("crypto" ) function encrypt (key,iv,data ){ let dep = crypto.createCipheriv ("aes-128-cbc" ,key,iv) return dep.update (data,'binary' ,'hex' ) + dep.final ("hex" ) } function decrypt (key,iv,crypted ){ crypted = Buffer .from (crypted,"hex" ).toString ("binary" ) let dep = crypto.createDecipheriv ("aes-128-cbc" ,key,iv) return dep.update (crypted,'binary' ,'utf8' )+dep.final ("utf8" ) } let key="abcdef1234567890" let iv="tbcdey1234567890" let data = "lam" let cryted = encrypt (key,iv,data)console .log ("加密结果-" ,cryted) let decrypted = decrypt (key,iv,cryted)console .log ("解密结果-" ,decrypted)