Express 是node 第三方框架,大家都知道,框架的意义就在于能大大简化程序地开发。那么我们就看一下Express是怎么简化node程序开发的。
1,用Express写一个hello world 程序,我们来体验一下Express 开发。
新建文件夹express,npm init -y 快速创建package.json, 再新建一个server.js 用于项目启动。由于express 是第三方框架,我们要先安装它,npm install express -S, server.js 代码如下:
let express = require("express"); let http = require("http"); let app = express(); app.use(function(req,res){ res.writeHead("200",{‘content-type‘:‘text/plain‘}) res.end("Hello World") }) http.createServer(app).listen(8080)
现在在当前文件夹中,调用cmd 命令窗口,输入node server 开启服务器,浏览器中输入localhost:8080 可以看到Hello World. 现在我们再把原生node 代码拿过来(如下),看一下,它们的区别。
let http = require("http"); // 创建请求处理函数 let app = function(req,res) { res.writeHead("200",{‘content-type‘:‘text/plain‘}) res.end("Hello World") } http.createServer(app).listen(8080)
原生node 程序和Express 程序最主要的区别的就是请求处理函数,原生node是直接创建一个函数来处理请求,所有请求和响应操作都放到这一个函数里。Express 则是调用 express()返回一个请求处理函数, 然后调用该函数的use方法来处理请求。
这里可以简单看一下express 的源码,看一下app请求处理函数, 当require(‘express’) 时,node 会寻找node_modules下面的express, 它是一个文件夹,就会寻找它下面的index.js 文件,这是node CommonJS 规范规定的。index.js 文件如下:
module.exports = require(‘./lib/express‘);
我们再看一下lib 文件夹下的express.js 文件(如下),可以看到它暴露出createApplication函数, 我们定义的express 变量就是指向这个函数,
exports = module.exports = createApplication
看一下这个函数(如下),它返回app. 所以当程序中执行express() 的时候,它返回了app, app 就是function(req,res,next) 函数, 就是我们的请求处理函数,mixin(app,proto,false), 就是给app
增加一些方法,如这里的use 方法。
function createApplication() { var app = function(req, res, next) { app.handle(req, res, next); }; mixin(app, EventEmitter.prototype, false); mixin(app, proto, false); // expose the prototype that will get set on requests app.request = Object.create(req, { app: { configurable: true, enumerable: true, writable: true, value: app } }) // expose the prototype that will get set on responses app.response = Object.create(res, { app: { configurable: true, enumerable: true, writable: true, value: app } }) app.init(); return app; }
到底app 有哪些方法,我们不妨把它打印出来。在文件夹中随便建一个js 文件,如 applog.js 看一下,看完之后就可以删除。在applog.js 中输入如下代码
let express = require("express"); let app = express(); console.log(app)
在命令行中输入node applog ,可以看到{ [Function: app] .... }等,可以看到它是一个函数, 还有use, set, post 等方法。
调用express()返回app 请求处理函数,然后调用app.use 来处理请求,这么写到到底有什么好处? 最主要的就是我们可以把请求处理,放到不同的函数进行,从而避免了在原生node 中只有一个函数进行处理的问题。把所有的处理逻辑放到一个函数,不利于代码的维护和扩展。
现在我们想要在响应之前输出请求日志,用Express,我们就可以直接在程序中填加app.use(), 而不用管以前的代码,而且原生node, 我们还要在请求处理函数中填加。Express 代码如下:
var express = require("express"); var http = require("http"); var app = express(); // 记录请求日志 app.use(function(request, response, next) { console.log("In comes a " + request.method + " to " + request.url); next(); }); // 对请求做出响应 app.use(function(request, response) { response.writeHead(200, { "Content-Type": "text/plain" }); response.end("Hello, world!"); }); http.createServer(app).listen(8080);
这样我们就把请求放到不同的函数中进行处理,这也是Express 的中间件思想,不是把http请求放到一个大的函数中进行处理,而是把请求进行分解,放到一堆函数中进行处理。这一堆函数中的每一个函数,就是一个中间件,就是我们app.use 中的函数, 并且express 保证了 这些函数按照我们书写的顺序进行执行。如果一个中间件(函数)只做一件事件,这有利于模块化,代码的复用,更重要的是可以引用第三方模块。