my-blog icon indicating copy to clipboard operation
my-blog copied to clipboard

:book:My blog

Results 65 my-blog issues
Sort by recently updated
recently updated
newest added

之前的文章里有说,在 Node.js 中,流(`stream`)是许许多多原生对象的父类,角色可谓十分重要。但是,当我们沿着“族谱”往上看时,会发现 `EventEmitter` 类是流(`stream`)类的父类,所以可以说,`EventEmitter` 类是 Node.js 的根基类之一,地位可显一般。虽然 `EventEmitter` 类暴露的接口并不多而且十分简单,并且是少数纯 `JavaScript` 实现的模块之一,但因为它的应用实在是太广泛,身份太基础,所以在它的实现里处处闪光着一些优化代码执行效率,和保证极端情况下代码结果正确性的小细节。在了解之后,我们也可以将其使用到我们的日常编码之后,学以致用。 好,现在就让我们跟随 Node.js 项目中的 `lib/events.js` 中的代码,来逐一了解: - 效率更高的 键 / 值 对存储对象的创建。 - 效率更高的从数组中去除一个元素。 - 效率更高的不定参数的函数调用。 - 如果防止在一个事件监听器中监听同一个事件,接而导致死循环? -...

Blog

关于 Go 语言最新的垃圾回收器(garbage collector),我最近阅读了许多篇赞扬它的文章,但是它们都让我将信将疑,其中的不少来自 Go 语言的官方团队博客。他们像是暗示着在垃圾回收领域已经发生了一个巨大的突破。 以下是这个垃圾回收器在 2015 年 8 月第一次被公之于众时的摘录: > Go 正在准备构建一个不仅属于 2015 年更属于 2025 年及未来的垃圾回收器。Go 1.5 的垃圾回收将会预示着 stop-the-world 不再会成为构建一个安全的编程语言的壁垒。届时应用可以被轻松高效的在硬件之间扩展。并且随着硬件越来越强大,软件的扩展性也会变得越来越强大,垃圾回收不再会成为其中的障碍。 Go 团队不仅声称他们已经解决了垃圾回收中的 stop-the-world 问题,并且还表示这将使你的编程体验会越发简易: > 目前一个比较高层次抽象且解决垃圾回收性能问题的方案是添加更多的垃圾回收预配置。编程人员可以根据他们应用程序的具体情况,选择不同的预配置来启动应用。这个方案的缺点就是,随着时间的推移,预配置变得越来越多,你也渐渐进入了其中的选择综合症中不能自拔。Go 的解决方案完全与之相反,它仅仅提供一种预配置,即 GOGC...

Blog

# fasthttp 文档手册 ## 常量 ``` go const ( CompressNoCompression = flate.NoCompression CompressBestSpeed = flate.BestSpeed CompressBestCompression = flate.BestCompression CompressDefaultCompression = flate.DefaultCompression ) ``` 所支持的压缩级别。 ``` go const ( StatusContinue =...

Blog

在 Node.js 中,当我们使用 `child_process` 模块创建子进程后,会返回一个 `ChildProcess` 类的实例,通过调用 `ChildProcess#send(message[, sendHandle[, options]][, callback])` 方法,我们可以实现与子进程的通信,其中的 `sendHandle` 参数支持传递 `net.Server` ,`net.Socket` 等多种句柄,使用它,我们可以很轻松的实现在进程间转发 TCP socket: ``` js // parent.js 'use stirct' const { createServer } =...

Blog

如果你已经阅读过了[上手指南](https://developers.google.com/v8/get_started),那么你已经知道了如何作为一个单独的虚拟机使用 V8 ,并且熟悉了一些 V8 中的关键概念,如**句柄**,**域** 和**上下文**。在本文档中,还将继续深入讨论这些概念并且介绍其他一些在你的 C++ 应用中使用 V8 的关键点。 V8 的 API 提供了编译和执行脚本,访问 C++ 方法和数据结构,处理错误和启用安全检查的函数。你的应用可以像使用其他的 C++ 库一样使用 V8 。你的 C++ 应用可以通过引入头文件 `include/v8.h` 来访问 V8 API 。 当你想要优化你的应用时,[V8 设计概要文档](https://developers.google.com/v8/design)可以提供很多有用的背景知识。 ##...

Blog

## 从coffeeScript迁移到ES6 我在多年前爱上了coffeScript。对于javaScript,我一直保持着深沉的爱,也十分高兴得看到node.js的快速发展,但是作为一个有python背景的程序员,我更喜欢coffeeScript的简练语法。 在任何一个活跃的社区中,事物的迭代更新都是必然的,现在,我们看见了javaScript向着ES6标准的巨大进步。ES6包含了相比于CoffeeScript更多好的特性,并且通过如[Babel](https://babeljs.io/)这样的工具,我们已经可以开始着手使用他们。以下是从coffeeScript迁移到ES6的一些注意点和我的想法。 ### 符号 放弃空格(`whitespace`),重新转而使用圆括号,花括号和分号。请接受在使用ES6时,你会敲上更多的符号。不过在规范的代码格式下,它们看上去还是挺整洁的。 ### 语法校验 过去我使用的是[CoffeeLint](https://www.npmjs.com/package/coffeelint),现在我通过[babel-eslint](https://github.com/babel/babel-eslint)来使用[ESLint](http://eslint.org/)。遵循[Airbnb ES6 style guide](https://github.com/airbnb/javascript)这个语法风格指南。最好将你的编辑器设置成在输入或保存时进行语法检查。[Atom's eslint plugin](https://atom.io/packages/linter-eslint)这个语法校验插件非常不错,你可以将上面的`Airbnb ES6 style guide`链接中的内容,放入你的`.eslintrc`配置文件中。SublimeText也有[类似的插件](https://github.com/roadhump/SublimeLinter-eslint)。 ### 代码转换(Transpiling) 由于现在离对ES6的完美支持还很远,所以最好还是使用代码转换器(Transpiling),如[Babel](https://babeljs.io/),就像在用CoffeeScript时一样。不过和CoffeeScript不同的是,这里有一些值得说明的: 1,并不是所有的ES6特性全部都可用,诸如`Proxies`。 2,另有一些ES6特性需要使用`polyfill/runtime`才可用,如Symbols,generator函数,WeakMap。一段`package.json`的例子: ``` json { ... "scripts": { "lint":...

Blog

## 前言 最近在回顾设计模式方式的知识,重新翻阅了[《JavaScript模式》](http://www.oreilly.com.cn/index.php?func=book&isbn=978-7-5123-2923-2)(个人感觉也算是一本小有名气的书了哈)一书,读时总有感触:在即将到来的ES6的大潮下,书中的许多模式的代码可用ES6的语法更为优雅简洁的实现,而另一些模式,则已经被ES6原生支持,如模块模式(99页)。所以自己动手用ES6重新实现了一遍里面的设计模式,算是对其的巩固,也算是与大家一起来研究探讨ES6语法的一些最佳实践。 ## 目录 (以下所有例子的原型均为《JavaScript模式》一书里“设计模式”章节中的示例) - [单例模式](#单例模式) - [迭代器模式](#迭代器模式) - [工厂模式](#工厂模式) - [装饰者模式](#装饰者模式) - [策略模式](#策略模式) - [外观模式](#外观模式) - [代理模式](#代理模式) - [订阅/发布模式](#订阅/发布模式) [代码repo地址](https://github.com/DavidCai1993/JsPattern-ES6),欢迎star,欢迎follow。 ## 实现 ### 单例模式 主要改变为使用了class的写法,使对象原型的写法更为清晰,更整洁: ``` js...

Blog

## 前言 如果你了解过`Node.js`,那么你一定听说过事件循环。你一定想知道它为什么那么特殊,并且为什么你需要关注它?此时此刻的你,可能已经写过许多基于`Express.js`的后端代码,但没有接触到任何的循环。 在下文中,我们会先在一个更高的,无关操作系统的层面上了解事件循环,然后再去深入到`Node.js`中观察它。 ## 事件和事件处理器 在事件循环里,有两个主要角色: - 事件 - 事件处理器,即这些事件的订阅者 事件,可以是十分底层的操作系统事件,如“文件已经准备好被写入”或“收到了一个新的HTTP请求”。 事件处理器,则是当指定事件触发时,执行的一段代码。 ## 事件循环中,事件的获取和事件处理器的执行 ![eventloop](http://bytearcher.com/articles/event-loop-10-000ft/event-loop.svg) 事件循环的职责,就是不断得等待事件的发生,然后将这个事件的所有处理器,以它们订阅这个事件的时间顺序,依次执行。当这个事件的所有处理器都被执行完毕之后,事件循环就会开始继续等待下一个事件的触发,不断往复。 当同时并发地处理多个请求时,以上的概念也是正确的,可以这样理解:在单个的线程中,事件处理器是一个一个按顺序执行的。 即如果某个事件绑定了两个处理器,那么第二个处理器会在第一个处理器执行完毕后,才开始执行。在这个事件的所有处理器都执行完毕之前,事件循环不会去检查是否有新的事件触发。在单个线程中,一切都是有顺序地一个一个地执行的! ## 在事件处理器的执行代码中触发了事件 一个有趣而且常会出现的情况是,在执行一个事件处理器的代码里,代码触发了另一个事件。例如,在文件可以被读之后,这个事件的处理器开始读取内容,期间处理器又触发了一个写事件,来将这个文件中已读取的这部分内容响应给正在处理的HTTP请求。写入完毕之后,继续读取文件。这就是事件循环保持运作的方式。 事件被触发,然后以订阅顺序执行处理器,不断往复。这个循环圈就是事件循环控制流的关键 ,在没有更多的订阅事件的处理器之后,`Node.js`就会退出。 ## 操作系统的帮助 事件在实质上是从哪里来?事件循环会不断获取下一个被触发的事件,这是如何发生的?你是对的,这需要操作系统的帮助。幸运的是,现代操作系统中有许多方式可以实现这些(`select`,`epoll`,`kqueue`,`IOCP`)。在日常使用时,通常会在操作系统提供的这些方式上会再抽象出一层(在`Node.js`中,就是`libuv`)。 另一个需要操作系统帮助的,就是事件的订阅,如注册在特定的事件发生时需要执行的代码。这也是事件循环中必须要实现的。 ## `Node.js`中的事件循环...

Blog

## 概述 libuv 最初是为 Node.js 所作的跨平台库。它基于事件驱动的异步 I/O 模型。 libuv 不仅仅只提供了对于不同 I/O 轮询机制的简单抽象:“句柄(handles)”和“流(streams)”也提供了对于 socket 和其他相关实例的高度抽象。同时 libuv 还提供了跨平台文件 I/O 接口和多线程接口等等。 下图展示了 libuv 的不同组成部分,以及与这些部分相关的子模块: ![architecture.png](http://dn-cnode.qbox.me/Fs3XJSgMznkpxd1Sa78Z6d42WR4J) ## 句柄(handles)和请求(requests) 为了能使用户介入事件循环(event loop),libuv 为用户提供了两个抽象:句柄和请求。 句柄表示一个在其被激活时可以执行某些操作且持久存在的对象。例如:当一个预备句柄(prepare handle)处于激活时,它的回调函数会在每次事件循环中被调用;每当一个新 TCP...

Blog

在 Node.js 中,许许多多的异步操作,都需要来一个兜底的超时,这时,就轮到 timer 登场了。由于需要使用它的地方是那么的多,而且都是基础的功能模块,所以,对于它性能的要求,自然是十分高的。总结来说,要求有: - 更快的添加操作。 - 更快的移除操作。 - 更快的超时触发。 接下来就让我们跟着 Node.js 项目中的 `lib/timer.js` 和 `lib/internal/linklist.js` 来探究它具体的实现。 ## 更快的添加 / 移除操作 说到添加和移除都十分高效的数据结构,第一个映入脑帘的,自然就是[链表](https://en.wikipedia.org/wiki/Linked_list)啦。是的,Node.js 就是使用了双向链表,来将 timer 的插入和移除操作的时间复杂度都降至 O(1) 。双向链表的具体实现便在 `lib/internal/linklist.js` 中:...

Blog