Node.js 如何找出循环依赖的文件?如何解决循环依赖问题?

本文重点是讲解如何解决循环依赖这个问题。关心这个问题是如何产生的,可以自行谷歌。 如何重现这个问题 // a.js const {sayB} = require('./b.js') sayB() function sayA () { console.log('say A') } module.exports = { sayA } // b.js const {sayA} = require('./a.js') sayA() function sayB () { console.log('say B') } module.exports = { sayB } 执行下面的代码 ➜ test git:(master) ✗ node a.js /Users/dd/wj-gitlab/tools/test/b.js:3 sayA() ^ TypeError: sayA is not a function at Object.<anonymous> (/Users/dd/wj-gitlab/tools/test/b.js:3:1) at Module._compile (module.js:635:30) at Object.Module._extensions..js (module.js:646:10) at Module.load (module.js:554:32) at tryModuleLoad (module.js:497:12) at Function.Module._load (module.js:489:3) at Module.require (module.js:579:17) at require (internal/module.js:11:18) at Object.<anonymous> (/Users/dd/wj-gitlab/tools/test/a.js:1:78) at Module._compile (module.js:635:30) sayA is not a function那么sayA是个什么呢,实际上它是 undefined ...

2018-10-29 09:21:03 · 2 min · Eddie Wang

shields小徽章是如何生成的?以及搭建自己的shield服务器

shields小徽章介绍 一般开源项目都会有一些小徽章来标识项目的状态信息,并且这些信息是会自动更新的。在shields的官网https://shields.io/#/, 上面有各种各样的小图标,并且有很多自定义的方案。 起因:如何给私有部署的jenkins制作shields服务? 私有部署的jenkins是用来打包docker镜像的,而我想获取最新的项目打包的jenkins镜像信息。但是私有的jenkins项目信息,公网的shields服务是无法获取其信息的。那么如果搭建一个私有的shields服务呢? 第一步:如何根据一些信息,制作svg图标 查看shields图标的源码,可以看到这些图标都是svg格式的图标。然后的思路就是,将文字信息转成svg图标。最后我发现这个思路是个死胡同, 有个npm包叫做,text-to-svg, 似乎可以将文本转成svg, 但是看了文本转svg的效果,果断就放弃了。 最后回到起点,看了shields官方仓库,发现一个templates目录,豁然开朗。原来svg图标是由svg的模板生成的,每次生成图标只需要将信息添加到模板中,然后就可以渲染出svg字符串了。 顺着这个思路,发现一个包shields-lightweight var shields = require('shields-lightweight'); var svgBadge = shields.svg('subject', 'status', 'red', 'flat'); 这个包的确可以生成和shields一样的小徽章,但是如果徽章中有中文,那么中文就会溢出。因为一个中文字符的宽度要比一个英文字符宽很多。 所以我就fork了这个项目,重写了图标宽度计算的方式。shields-less npm install shields-less var shieldsLess = require('shields-less') var svgBadge = shieldsLess.svg({ leftText: 'npm 黄河远上白云间', rightText: 'hello 世界' }) var svgBadge2 = shieldsLess.svg({ leftText: 'npm 黄河远上白云间', rightText: 'hello 世界', style: 'square' }) var svgBadge2 = shieldsLess.svg({ leftText: 'npm 黄河远上白云间', rightText: 'hello 世界', leftColor: '#e64a19', rightColor: '#448aff', style: 'square' // just two style: square and plat(default) }) 渲染后的效果,查看在线demo: https://wdd.js.org/shields-less/example/ ...

2018-10-29 09:14:43 · 1 min · Eddie Wang

Express代理中间件问题与解决方案

前后端分离应用的架构 在前后端分离架构中,为了避免跨域以及暴露内部服务地址。一般来说,我会在Express这层中加入一个反向代理。 所有向后端服务访问的请求,都通过代理转发到内部的各个服务。 这个反向代理服务器,做起来很简单。用http-proxy-middleware这个模块,几行代码就可以搞定。 // app.js Object.keys(proxyTable).forEach(function (context) { app.use(proxyMiddleware(context, proxyTable[context])) }) http-proxy-middleware实际上是对于node-http-proxy的更加简便的封装。node-http-proxy是http-proxy-middleware的底层包,如果node-http-proxy有问题,那么这个问题就会影响到http-proxy-middleware这个包。 最近的bug http-proxy-middleware最近有个问题,请求体在被代理转发前,如果请求体被解析了。那么后端服务将会收不到请求结束的消息,从浏览器的网络面板可以看出,一个请求一直在pending状态。 Cannot proxy after parsing body #299, 实际上这个问题在node-http-proxy也被提出过,而且处于open状态。POST fails/hangs examples to restream also not working #1279 目前这个bug还是处于open状态,但是还是有解决方案的。就是将请求体解析的中间件挂载在代理之后。 下面的代码,express.json()会对json格式的请求体进行解析。方案1在代理前就进行body解析,所有格式是json的请求体都会被解析。 但是有些走代理的请求,如果我们并不关心请求体的内容是什么,实际上我们可以不解析那些走代理的请求。所以,可以先挂载代理中间件,然后挂载请求体解析中间件,最后挂载内部的一些接口服务。 // 方案1 bad app.use(express.json()) Object.keys(proxyTable).forEach(function (context) { app.use(proxyMiddleware(context, proxyTable[context])) }) app.use('/api', (req, res, next)=> { }) // 方案2 good Object.keys(proxyTable).forEach(function (context) { app.use(proxyMiddleware(context, proxyTable[context])) }) app.use(express.json()) app.use('/api', (req, res, next)=> { }) 总结 经过这个问题,我对Express中间件的挂载顺序有了更加深刻的认识。 同时,在使用第三方包的过程中,如果该包bug,那么也需要自行找出合适的解决方案。而这个能力,往往就是高手与新手的区别。

2018-09-30 09:41:44 · 1 min · Eddie Wang

IE11跨域检查跨域设置

IE11有安全设置中有两个选项, 跨域浏览窗口和框架 通过域访问数据源 如果上面两个选项被禁用,那么IE11会拒绝跨域请求。如果想要跨域成功,必须将上面两个选项设置为启用。 第一步 打开IE11 点击浏览器右上角的齿轮图标 点击弹框上的 Internet选项 第二步 点击安全 点击Internet 点击自定义级别 第三步 找到跨域浏览窗口和框架 如果这项是禁用的,那么要勾选启用。 找到通过域访问数据源 如果这项是禁用的,那么要勾选启用。 最后在点击确定。 最后,如果跨域浏览窗口和框架,通过域访问数据源都启用了,还是无法跨域。那么最好重启一下电脑。有些设置可能在重启后才会生效。

2018-08-23 10:20:10 · 1 min · Eddie Wang

毕业后,青春像一艘船,沉入海底

大三那年的暑假 大三那年暑假,很多同学都回去了,寝室大楼空空如也。 留在上海的同学都在各自找着兼职的工作,为了不显得无聊,我也在网上随便发了一些简历,试试看运气。 写简历最难写的部分就是写你自己的长处是什么?搜索枯肠,觉得自己似乎也没什特长。感觉大学三年学到一些东西,又感觉什么都没学到。 如果没有特长,总该也有点理想吧,比如想干点什么? 似乎我也没什么想做的事情。 小时候我们都有理想,慢慢长大后,理想越来越模糊,变得越来越迷茫。 大学里,大部分的人都是在打游戏。我也曾迷恋过打游戏,但是因为自己比较菜,总是被虐,所以放弃了。 但是我也不是那种天天对着笔记本看电视剧的人。 回忆初三那年的暑假 记得,初三的暑假,我参加了一个学校看展的一个免费的计算机培训班。因为培训的老师说,培训结束前会有一个测试,成绩最好的会有几百块的奖励。 为了几百块的奖励,我第一个背诵完五笔拆字法。随后老师教了我们PS, 就是photoshop。当时我的理解就是,ps可以做出很多搞笑的图片。 为了成为一个有能力做出搞笑图片的人。我在高中和大学期间,断断续续的系统的自学了PS。 下面给展示几张我的PS照片 【毕业照】 【帮别人做的艺术照】 【刺客信条 换脸 我自己】 【旅游照 换脸 我自己】 【宿舍楼 上面ps了一条狼】 古玩艺术电商中的店小二 基本上,我的PS技术还是能够找点兼职做的。没过多久,我收到了面试邀请,面试的公司位于一个古玩收藏品市场中。 当然我面试成功了,开出的日薪也是非常诱人,每天35元。 在上海,35元一天的工资,除去来回上下班做地铁和公交,还有中午饭的费用外,基本上不会剩下什么,有时候稍微午饭丰盛点,自己就要倒贴。但是这也是一次不错的尝试,至少有史以来,除去父母以外,我用能力问别人要钱了。 35元的日薪持续很短一段时间,然后我就涨薪了,到达每天100元。在这个做兼职的地方,我最高拿到的日薪是200元。 兼职期间我做了各式各样的工作: 古玩艺术品摄影 海报制作 拍卖图册制作 linux运维 APP UI 设计 网页设计 python爬虫 兼职的日志过得很苦,单是还算充实。虽然工资不高,但是因为还没毕业,也没有奢望过高的工资。 【上图 我在一个古玩店的拍摄玉器的时候,有个小女孩过来找我玩,我随手拍的】 【上图 是在1号线 莲花路地铁站 因为错过了地铁拍的】 【上图 是从1号线 莲花地铁站 转公交拍的】 【每天早上起的很早,能够看到军训的学生在操场上奔跑】 【在古玩店一般都要拍到很晚,因为是按张数算拍照工资,拍的越多,工资越高。还好晚上回公司 打车费用是可以报销的】 ...

2018-08-14 18:36:40 · 1 min · Eddie Wang

NodeJS Events 模块笔记

1. 环境 node 8.11.3 2. 基本使用 // 01.js const EventEmitter = require('events'); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); myEmitter.on('event', () => { console.log('an event occurred!'); }); myEmitter.emit('event'); 输出: an event occurred! 3. 传参与this指向 emit()方法可以传不限制数量的参数。 除了箭头函数外,在回调函数内部,this会被绑定到EventEmitter类的实例上 // 02.js const EventEmitter = require('events') class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter() myEmitter.on('event', function (a, b){ console.log(a, b, this, this === myEmitter) }) myEmitter.on('event', (a, b) => { console.log(a, b, this, this === myEmitter) }) myEmitter.emit('event', 'a', {name:'wdd'}) 输出: ...

2018-08-10 10:18:57 · 2 min · Eddie Wang

JavaScript动态下载文件

需求描述 可以把字符串下载成txt文件 可以把对象序列化后下载json文件 下载由ajax请求返回的Excel, Word, pdf 等等其他文件 基本思想 downloadJsonIVR () { var data = {name: 'age'} data = JSON.stringify(data) data = new Blob([data]) var a = document.createElement('a') var url = window.URL.createObjectURL(data) a.href = url a.download = 'what-you-want.json' a.click() }, 从字符串下载文件 从ajax请求中下载文件

2018-06-27 09:09:01 · 1 min · Eddie Wang

Restful API 架构思考

1. 什么是REST? 2. REST API最为重要的约束 3. REST API HTTP方法 与 CURD 4. 状态码 5. RESTful架构设计 6. 文档 7. 版本 8. 深入理解状态与无状态 9. 参考 1. 什么是REST? 表现层状态转换(REST,英文:Representational State Transfer)是Roy Thomas Fielding博士于2000年在他的博士论文[1] 中提出来的一种万维网软件架构风格,目的是便于不同软件/程序在网络(例如互联网)中互相传递信息。表现层状态转换(REST,英文:Representational State Transfer)是根基于超文本传输协议(HTTP)之上而确定的一组约束和属性,是一种设计提供万维网络服务的软件构建风格。匹配或兼容于这种架构风格(简称为 REST 或 RESTful)的网络服务,允许客户端发出以统一资源标识符访问和操作网络资源的请求,而与预先定义好的无状态操作集一致化。wikipdeia REST API 不是一个标准或者一个是协议,仅仅是一种风格,一种style。 RESTful API的简单定义可以轻松解释这个概念。 REST是一种架构风格,RESTful是它的解释。也就是说,如果您的后端服务器具有REST API,并且您(从网站/应用程序)向客户端请求此API,则您的客户端为RESTful。 2. REST API最为重要的约束 Client-Server 通信只能由客户端单方面发起,表现为请求-响应的形式 Stateless 通信的会话状态(Session State)应该全部由客户端负责维护 Cache 响应内容可以在通信链的某处被缓存,以改善网络效率 Uniform Interface 通信链的组件之间通过统一的接口相互通信,以提高交互的可见性 Layered System 通过限制组件的行为(即每个组件只能“看到”与其交互的紧邻层),将架构分解为若干等级的层。 Code-On-Demand 支持通过下载并执行一些代码(例如Java Applet、Flash或JavaScript),对客户端的功能进行扩展。 3. REST API HTTP方法 与 CURD REST API 使用POST,GET, PUT, DELETE的HTTP方法来描述对资源的增、查、改、删。 这四个HTTP方法在数据层对应着SQL的插入、查询、更新、删除操作。 ...

2018-06-07 22:35:08 · 1 min · Eddie Wang

记一次如何解决谷歌浏览器占用过高cpu问题过程

1. 问题现象 有时候发现mac风扇响的厉害,于是我检查了mac系统的活动监视器,发现Google Chrome Helper占用99%的CPU。 通常来说Chrome如果占用过高的内存,这并不是什么问题,毕竟Chrome的性能以及易用性是建立在占用很多内存的基础上的。但是无论什么程序,持续的占用超过80%的cpu,都是极不正常的。大多数程序都是占用维持在低于10%的CPU。 活动监视器指出问题出现在Chrome浏览器。那么问题可以再次细分为三块。 Chrome系统自身问题 一些插件,例如flash插件,扩展插件 网页程序js出现的问题 2. 从任务管理器着手 其实Chrome浏览器自身也是有任务管理器的,一般来说windows版chrome按住shift+esc就会调出任务管理器窗口。mac版调出任务管理器没有快捷,只能通过Window > Task Manager调出。 调出任务管理器后,发现一个标签页,CPU占用率达到99%, 那就说明,应该是这个标签页中存在持续占用大量CPU计算的程序。 最后找到这个页面,发现该页面背景图是一种动态粒子图。就是基于particles.js做的。我想,终于找到你了。 于是我把这个动态图的相关js代码给注释掉,电脑的风扇也终于变得安静了。 3. 问题总结 问题解决的总结:解决问题的方法时很简单的,基于一个现象,找到一个原因,基于这个原因再找到一个现象,然后一步一步缩小问题范围,逼近最终原因。 机器CPU过高,一般都是可以从任务管理器着手解决。系统的任务管理器可以监控各个程序占用的CPU是否正常,通常程序自身也是有任务管理的。 像谷歌浏览器这种软件,几乎本身就是一个操作系统,所以说它的任务管理器也是必不可少的。Chrome浏览器再带的任务管理器可以告诉你几个关键信息。 任务占用的内存 任务占用的CPU 任务占用的网络流量大小 如果你一打开谷歌浏览器,你的电脑风扇就拼命转,那你最好打开谷歌浏览器的任务管理器看看。 4. 关于动态背景图的思考 动态背景图往往都会给人很酷炫的感觉,但是这种背景图的制作并不是很复杂,如果你使用particles.js来制作,制作一些动态背景图只需要几行代码就可以搞定。但是这种酷炫的背后,CPU也在承受着压力。 particles.js提供的demo效果图,在Chrome中CPU会被提高到100%。 也有几家使用动态背景图的官网。我记得知乎以前就用过动态背景图,但是现在找不到了。另外一个使用动态背景图的是daocloud, CPU也是会在首页飙升到50%。 所谓:强招必自损,动态背景图在给人以炫酷科技感的同时,也需要权衡这种技术对客户计算机的压力。 另外,不要小看JavaScript, 它也可能引起大问题

2018-06-04 17:58:24 · 1 min · Eddie Wang

IE浏览器不支持location.origin

某些IE浏览器location.origin属性是undefined,所以如果你要使用该属性,那么要注意做个能力检测。 if (!window.location.origin) { window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port: ''); }i

2018-05-24 14:50:49 · 1 min · Eddie Wang