koa
koa一直有所耳闻,没怎么用过,因为express在公司内部项目较多而且较为成熟,一直找不到使用koa的理由。最近在搭公司的npm源,看了下淘宝的cnpm,发现其是基于koa实现的。所以看了下koa框架。
使用
koa基本设计和express很类似,通过中间件来处理各个请求。但是其主要设计都是和generator有关,还是有不一样的地方,我主要不是关注使用,这部分可以参考官网:http://koajs.com/
koa一直有所耳闻,没怎么用过,因为express在公司内部项目较多而且较为成熟,一直找不到使用koa的理由。最近在搭公司的npm源,看了下淘宝的cnpm,发现其是基于koa实现的。所以看了下koa框架。
koa基本设计和express很类似,通过中间件来处理各个请求。但是其主要设计都是和generator有关,还是有不一样的地方,我主要不是关注使用,这部分可以参考官网:http://koajs.com/
当ECMAScript引擎执行一段ECMAScript程序的时候,进入不同的可执行程序会创建不同的可执行上下文。比如进入全局代码,会创建全局上下文,进入函数代码,会创建函数上下文。其中函数上下文最具有代表性,进入一段函数代码会发生下面的事情:
var http = require('http'); http.createServer(function(req, res) { res.write('ok'); res.end(); }).listen(3000);
本文主要想探索一下上面这段代码在nodejs内部到底发生了什么?
nodejs源码在github上面,其中js部分源码存在了 node/lib 目录下。我们先看 http 模块的代码。node/lib/http.js
:
const server = require('_http_server'); ... const Server = exports.Server = server.Server; ... exports.createServer = function(requestListener) { return new Server(requestListener); };
可以清楚的看出,createServer返回了一个Server的实例,然后将用户的回调传递进去,Server来自node/lib/_http_server_
:
function Server(requestListener) { if (!(this instanceof Server)) return new Server(requestListener); net.Server.call(this, { allowHalfOpen: true }); if (requestListener) { this.addListener('request', requestListener); } this.httpAllowHalfOpen = false; this.addListener('connection', connectionListener); this.addListener('clientError', function(err, conn) {...}); this.timeout = 2 * 60 * 1000; } util.inherits(Server, net.Server);从上面代码可以看出,Server会继承net.Server,同时自己增加了 httpAllowHalfOpen(用到再说) 和默认的超时时间(2min),绑定了三个事件(onrequest-即用户在createServer传递的事件、onconnection和onclientError); 先不管事件,继续看 net.Server,位于`node/lib/net.js`:
function Server(options, connectionListener) { // options: { allowHalfOpen: true }, connectionListener: undefined ... events.EventEmitter.call(this); //继承事件,让server拥有事件能力 ... this._connections = 0; //这一段定义connections了connections,标记其get set时候都不能被外部使用,否则打印一个warning Object.defineProperty(this, 'connections', { get: internalUtil.deprecate(function() { if (self._usingSlaves) { return null; } return self._connections; }, 'Server.connections property is deprecated. ' + 'Use Server.getConnections method instead.'), set: internalUtil.deprecate(function(val) { return (self._connections = val); }, 'Server.connections property is deprecated.'), configurable: true, enumerable: false }); this._handle = null; this._usingSlaves = false; this._slaves = []; this._unref = false; this.allowHalfOpen = options.allowHalfOpen || false; this.pauseOnConnect = !!options.pauseOnConnect; //---------调用结束--------- } util.inherits(Server, events.EventEmitter);//继承事件,让server拥有事件能力由上,实际上net.Server不过是定义了一堆变量挂在自己身上,因此 http Server也挂了这些属性到this上面。到此,createServer其实已经结束了。
事件驱动、异步、单线程、非阻塞I/O,这是我们听得最多的关于nodejs的介绍,连nodejs官网都是这么写的:
Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.
过去很长时间里,我都愿意接受这些“耳熟能详”的观点,直到最近,遇到过很多性能问题之后,我才开始思考,nodejs的内部机制到底是怎样的,nodejs的性能瓶颈在哪里?
#问题
以ES6的 promise 为准。
在处理一个异步操作时,如果希望通过promise来实现,我们只需要两步:
function someSyncFn() { return new Promise(function(resolve, reject) { setTimeout(function() { console.log("after 2s"); resolve(2000); }, 2000); }) }
someSyncFn().then(function(value) { console.log("getValue:" + value); });