Node 主要用在开发 web 应用, koa 是目前 node 里最流行的 Web 框架.
在 Node 开启一个 http 服务简直易如反掌, 官网 demo.
- const http = require("http");
- const server = http.createServer((req, res) => {
- res.statusCode = 200;
- res.setHeader("Content-Type", "text/plain");
- res.end("Hello World\n");
- });
- const hostname = "127.0.0.1";
- const port = 3000;
- server.listen(port, hostname, () => {
- console.log(`Server running at http://${hostname}:${port}/`);
- });
- // 前端全栈学习交流圈: 866109386
- // 面向 1-3 经验年前端开发人员
- // 帮助突破技术瓶颈, 提升思维能力
引入 http 模块, http 的 createServer 方法创建了一个 http.Server 的实例.
server 监听 3000 端口.
我们传入到 createServer 里的函数实际是监听 request 事件的回调, 每当请求进来, 监听函数就会执行.
request 事件的监听函数, 其函数接受两个参数, 分别是 req 和 res . 其中 req 是一个可读流, res 是一个可写流. 我们通过 req 获取 http 请求的所有信息, 同时将数据写入到 res 来对该请求作出响应.
koa 应用
koa 如何创建一个 server, 直接上个官网的例子
- const Koa = require("koa");
- const App = new Koa();
- // x-response-time
- App.use(async (ctx, next) => {
- const start = Date.now();
- await next();
- const ms = Date.now() - start;
- ctx.set("X-Response-Time", `${ms}ms`);
- });
- // logger
- App.use(async (ctx, next) => {
- const start = Date.now();
- await next();
- const ms = Date.now() - start;
- console.log(`${ctx.method} ${ctx.url} - ${ms}`);
- });
- // response
- App.use(async ctx => {
- ctx.body = "Hello World";
- });
- App.listen(3000);
- // 前端全栈学习交流圈: 866109386
- // 面向 1-3 经验年前端开发人员
- // 帮助突破技术瓶颈, 提升思维能力
中间件概念在编程中使用广泛, 不管是前端还是后端, 在实际编程中或者框架设计都有使用到这种实用的模型.
基本上, Koa 所有的功能都是通过中间件实现的.
每个中间件默认接受两个参数, 第一个参数是 Context 对象, 第二个参数是 next 函数. 只要调用 next 函数, 就可以把执行权转交给下一个中间件.
如果中间件内部没有调用 next 函数, 那么执行权就不会传递下去.
多个中间件会形成一个栈结构 (middle stack), 以 "先进后出"(first-in-last-out) 的顺序执行. 整个过程就像, 先是入栈, 然后出栈的操作.
上面代码的执行顺序是:
请求 ==> x-response-time 中间件 ==> logger 中间件 ==> response 中间件 ==> logger 中间件 ==> response-time 中间件 ==> 响应
理解 Koa 的中间件机制(源码分析)
阅读源码, 化繁为简, 我们看看 koa 的中间件系统是如何实现的.
- function compose(middleware) {
- return function(context, next) {
- // last called middleware #
- let index = -1;
- return dispatch(0);
- function dispatch(i) {
- if (i <= index)
- return Promise.reject(new Error("next() called multiple times"));
- index = i;
- let fn = middleware[i];
- if (i === middleware.length) fn = next;
- if (!fn) return Promise.resolve();
- try {
- return Promise.resolve(fn(context, dispatch.bind(null, i + 1)));
- } catch (err) {
- return Promise.reject(err);
- }
- }
- };
- }
- // 前端全栈学习交流圈: 866109386
- // 面向 1-3 经验年前端开发人员
- // 帮助突破技术瓶颈, 提升思维能力
我试图去简化一下这个方法, 但方法本身已经足够简洁.
代码很简洁.
通过 next()传递 实现中间件调用, 结合 Promise 采用 递归调用 的通知机制.
看图
这种形式的控制流让整个 Koa 框架中间件的访问呈现出 自上而下的中间件流 + 自下而上的 response 数据流 的形式.
Koa 本身做的工作仅仅是定制了中间件的编写规范, 而不内置任何中间件. 一个 Web request 会通过 Koa 的中间件栈, 来动态完成 response 的处理.
koa 在中间件语法上面采用了 async + await 语法来生成 Promise 形式的程序控制流.
来源: http://www.jianshu.com/p/2e1baccc1282