Node.js的循环依赖-深圳SEO优化公司
公众号矩阵
移动端
开发 前端
循环依赖,简单点来说就是a文件中require b文件,然后b文件中又反过来require a文件。这个问题我们平时可能并不大注意到,但如果处理不好可能会引起一些让人摸不清的问题。在node中,是如何处理循环依赖的问题的呢?

循环依赖,简单点来说就是a文件中require b文件,然后b文件中又反过来require a文件。这个问题我们平时可能并不大注意到,但如果处理不好可能会引起一些让人摸不清的问题。在node中,是如何处理循环依赖的问题的呢?

51CTO推荐专题:Node.js专区

写个简单的例子来试验一下看吧。

定义两个文件:

a.js

  1. var b = require('./b');  
  2. console.log('a.js get b:' + b.b);  
  3. module.exports.a = 1; 

b.js

  1. var a = require('./a');  
  2. console.log('b.js get a:' + a.a);  
  3. module.exports.b = 2; 

执行

node a.js

输出的结果是

b.js get a:undefined

a.js get b:2

从打印的轨迹上来看,代码执行的流程大致如下:

  1. a.js:                               b.js:  
  2.  
  3. var b = require('./b');  
  4.  
  5.                                     var a = require('./a'); // a = {}  
  6.  
  7.                                     console.log('b.js get a:' + a.a);  
  8.  
  9.                                     module.exports.b = 2;  
  10.  
  11. // b = {b: 2}  
  12.  
  13. console.log('a.js get b:' + b.b);  
  14.  
  15. module.exports.a = 1; 

node的加载过程,可以在lib/module.js文件中找到。与这个过程相关的代码主要集中在Module._load方法里。可以看到,node会为每个新加载的文件创建一个Module对象(假设为a),这个就是我们在a.js代码中看到的module了。在创建a之后,node会先将a放到cache中,然后再对它进行加载操作。也就是说,如果在加载a的过程中,有其他的代码(假设为b)require a.js的话,那么b可以从cache中直接取到a的module,从而不会引起重复加载的死循环。但带来的代价就是在load过程中,b看到的是不完整的a,也就是为什么前面打印undefined的原因。

Module的构造函数

  1. function Module(id, parent) {  
  2.   this.id = id;  
  3.   this.exports = {};  
  4.   this.parent = parent;  
  5.   this.filename = null;  
  6.   this.loaded = false;  
  7.   this.exited = false;  
  8.   this.children = [];  

Module._load方法

  1. Module._load = function(request, parent, isMain) {  
  2.   //...  
  3.   var module = new Module(id, parent);  
  4.   //...  
  5.   Module._cache[filename] = module;  
  6.   try {  
  7.     module.load(filename);  
  8.   } catch (err) {  
  9.     delete Module._cache[filename];  
  10.     throw err;  
  11.   }  
  12.   return module.exports;  
  13. }; 

这个看似简单粗暴的处理手法,但实际上是node作者权衡各方面因素的结果。我们敬爱的npm作者issacs强调说了,这不是bug,而且近期内不会做什么改变。当然,issacs也给出了一些规避这个陷阱的建议(具体可以参考后面给的链接[1])。我总结了一下,主要有两点:一个是在造成循环依赖的require之前把需要的东西exports出去;另一个是不要在load过程中操作未完成的模块。

所以上面的例子的一种处理方法就是把各自的exports语句放到require语句前面,然后再运行,可以看到打印了正确的值。

从前面的分析来看,循环依赖的陷阱出现的条件比较苛刻:一个是循环依赖,另一个是在load期间调用未加载完成的对象。所以大家平常不怎么会遇到。但我之前就曾华丽丽的邂逅了这个陷阱,在这里拿出来当一下反面教材。。。

场景简化后大致如下:我有一堆service,每一个service负责消费某一类消息,并且可能会产生新的消息给其他service消费。从消息传递上来看,并没有产生循环依赖。但我为了解耦,定义了一个消息中心center的角色出来进行消息分发。center主要是维护一个type -> service的map来路由消息,这样center就得把所有的service加载进来,于是产生了center->service的依赖。另一面,每个service又需要通过center来分发它们新产生的消息,于是又出现了service->center的依赖,循环依赖就这么出来了。刚好在service加载的过程中,又调用了center的一个方法,就发生了undefined的错误。

这个问题查清楚原因以后,解决起来并不困难。

一种方法就是按前面的方法,在代码层面上规避循环依赖的陷阱;

另外也可以在设计的层面上彻底避免循环依赖的出现。我的场景之所以出现循环依赖,是因为center和service都需要知道对方的存在,即 center <- -> service。如果采用依赖注入的方式,则可以切断这种直接依赖,类似于center <- container -> service。即加入一个container角色,把center和service都先加载进来,然后再用IOC的方法把依赖关系建立好。这样center和service都无须知道对方具体的文件所在了,也就不会循环的require对方了。

总的来说,循环依赖的陷阱并不大容易出现,但一旦出现了,在实际的代码中也许还真不好定位。它的存在给我们提了个醒,注意你工程中的依赖关系。哪天node对你抱怨,一个你明明已经exports了的方法undefined,我们就该提醒一下自己:哦,也许是它来了:)

原文:http://club.cnodejs.org/topic/4f16442ccae1f4aa27001045

【编辑推荐】

  1. 用Eclipse调试Node.js代码
  2. 用Web socket和Node.js实现HTML 5画布的实时绘图
  3. Node.js后端框架设计构想
  4. 走近Node.js的异步代码设计
  5. 使用Node.js开发多人玩的HTML 5游戏
责任编辑:陈贻新 来源: CNode
相关推荐

2021-05-27 09:00:00

Node.js开发线程

2024-01-05 08:49:15

Node.js异步编程

2011-09-08 14:16:12

Node.js

2021-12-18 07:42:15

Ebpf 监控 Node.js

2023-01-31 16:43:31

​Node.js事件循环

2013-11-01 09:34:56

Node.js技术

2015-03-10 10:59:18

Node.js开发指南基础介绍

2020-05-29 15:33:28

Node.js框架JavaScript

2021-12-25 22:29:57

Node.js 微任务处理事件循环

2011-11-01 10:30:36

Node.js

2011-09-02 14:47:48

Node

2011-09-08 13:46:14

node.js

2011-09-09 14:23:13

Node.js

2021-10-22 08:29:14

JavaScript事件循环

2012-10-24 14:56:30

IBMdw

2011-11-10 08:55:00

Node.js

2011-11-02 09:04:15

Node.js

2021-09-26 05:06:04

Node.js模块机制

2021-11-06 18:40:27

js底层模块

2019-07-09 14:50:15

Node.js前端工具
后端
26302内容
全部话题

同话题下的热门内容

66.4K Star!别再熬夜写样式!Screenshot-to-Code:截图秒变代码!Java并发编程:深入理解Java线程状态惊艳到了,每个开发人员都必须要知道的六个HTML属性!一文搞懂HashMap如何优雅处理哈希冲突当执行kubectl exec时,你真的进入容器了吗?深度解析容器访问原理真香!全面解析 Spring Boot 插件化开发模式如何使用GitHub Actions自动化部署我们的项目Spring Boot 开发中有七件事,你必须知道

相关专题 更多

2024年第十九届中国企业年终评选榜单揭晓
2024年第十九届中国企业年终评选榜单揭晓
如何发挥数据的最大力量?
如何发挥数据的最大力量?
2024-09-11 10:06:01
戴尔与AMD携手发布新一代服务器解决方案
戴尔与AMD携手发布新一代服务器解决方案
2024-12-24 16:34:07
我收藏的内容
点赞
收藏
分享

51CTO技术栈公众号

业务
速览
在线客服
媒体
51CTO CIOAge HC3i
社区
51CTO博客 鸿蒙开发者社区 AI.x社区
教育
51CTO学堂 精培 企业培训 CTO训练营

相关内容推荐

seo运营团队seo续费老鸿SEOseo行业如何爱站网seo培训视频重庆做seo选哪家好南京seo网站优化推广分享seo网站seo搜索九龙坡区seo前端框架的seo肇庆关键词seo优化台湾黄怡嘉seoseo是谁博客seo教程seo班seo快速排名软件如何seo手机关键字排行榜公司seo工作日常seo平均工资seo排名快速优化易seoseo排名工具如何网络渠道专业seo排位seo的产生seo技术知识T1seoseo pack关键词seo优化工具seo优化基本操作汉文seo西安seo服务西安搜推宝超牛共同引用 seo淘宝seo pdf网站关键字seo淘宝seo引擎优化中山seo服务公司seo优化排名工具优质商家seo服务哪家好seo 百度优化seo优化网站优化合肥seo培训班seo推广销售学习seo步骤哪些行业适合做seo伪静态 对 seoseo搜索优化怎么做seo课程培训视频seo按天计费源码淘宝客网站seo专业seo网络培训海外seo优化外包上海最专业的seo公司seo价位seo是优化吗seo网络搜索引擎优化新疆SEO优化的seoseo营销方式360seo优化合肥seo优化外包公司温岭seo长沙seo霜天seo为什上海seo服务外包公司武林SEO寒冰seoseo搜外网seo 互点深圳seo培训机构qq空间seoseo衣服seo优化的课程西安市seo排名按天优化中山seo排名扣费希望免费seoseo 武汉seo tool新乡seo优化公司seo如何做站内优化seo关键词策略泉州seo优化推广seo词语贵阳seo营销seo需要多少钱SEO快速排名是什么seo站长常用工具宁波网站SEO优化seo因素seo云搜seo研究中心 vipF2SeO陕西网站seoseo 考核北京seo优化关键词吃鸡seo上海哪家SEO好seo智能软件关键词seo优化排名推荐杭州seo企业拓词 seo北京SEO推广公司北京seo怎么优化在线seo课程深圳好的seo公司延边SEO昆明网站seoseo工资怎么样seo 名词解释广州seo优化公司排名seo标题关键词seo报表模板北京seo培训机构排名seo培训有用吗蜘蛛 seo北京搜索引擎seoseo推广什么意思seo发家seo学习教程网seo手机工具夫唯 seoseo60丰都seo排名优化怎么做seo如何优化关键词排名郴州seo快排怎么做网站的seoseo主要是做什么的seo首页排名小黄人seoso2 seo2seo急救seo主管工作seo关键词搜索企业网站seo优化外包pdf seoseo课程有哪些中山seo公司电话企SEO东莞seo建站优化推广基础seo培训班西宁seo公司seo去哪学哈尔滨 seo北京seo优化推广seo引流软件昆明百度seoseo新手该做什么郑州seo网站有优化itmc电子商务 seo杨浦seo公司重庆知名seo公司河东SEO聊城seo优化seo培训吧本地seo排名团队seo课程在哪培训好seo的开发菠菜黑帽seoseo招标怎么站seo西安seo优化外包公司seo01网《seo盐城seo公司rss seoseo网络推广方法seo互点软件成都SEO优化排名seo 20日新闻营销seorobots seoseo综合优化平台seo搜索引擎优化自学seo标题优化工具网页seo靠谱怎么做关键词seo优化小芳seo成都谷歌seo关键词优化软件乐云seoseo招工网络推广seo培训seo高手教程东莞seo优化排名大全SEO培训顾问什么是seo搜索下载seoseo 任务seo维度武汉优化seo公司seo排名优化排行搜索引擎seo优化外包seo网站优seo优化推广广州seo优化技术seo互点击模板seo案例线路1seo查询seo傻妞seoseo用途网站seo谷歌

合作伙伴

深圳SEO优化公司

龙岗网络公司
深圳网站优化
龙岗网站建设
坪山网站建设
百度标王推广
天下网标王
SEO优化按天计费
SEO按天计费系统