项目运行
cnpm run start(从package.json里面scripts项查找)
notEmpty=true;
代表url里面的参数是必选项
optional=true;
代表可选
app.js的主要作用:附加中间件、请求参数校验、登录鉴权
cors 跨域资源共享是用来避开浏览器的同源策略,在处理app.get等请求之前使用
import cors from 'cors';
app.use(cors());
解析Content-Type: application/x-www-form-urlencoded
import bodyParser from 'body-parser';
app.use(bodyParser.urlencoded({
limit: '50mb',
extended: true
}));
解析Content-Type: application/json
import bodyParser from 'body-parser';
app.use(bodyParser.json());
打印请求日志
let requestLog = require('./src/libs/request-log');
app.use(requestLog);
校验请求参数
import expressValidator from 'express-validator';
app.use(expressValidator());
隐藏来至前端form产生的非Get和Post请求。
import methodOverride from 'method-override';
app.use(methodOverride());
因为浏览器的form只能产生Get和Post请求,但后端的API自然希望form能够产生其他的Put、Delete请求了,这时我们就需要method-override来帮我们来实现将get和post改成其他谓词put,delete等
常规的处理方法是在form中加入一个名为_method的隐藏输入换件,让这个控件承载我们实际需要的谓词,然后在服务器用这个控件的谓词进行方法的改写。
var express = require('express'),
bodyParser = require('body-parser'),
methodOverride = require('method-override');
function edit (req,res,next) {
if(req.method !== 'GET') {
return next();
}
res.setHeader('Content-Type','text/html');
res.write('<form method="post">');
res.write('<input type="hidden" name="post_to_put" value="put"/>');
res.write('<input type="text" name=user[name] value="Tobi"/>');
res.write('<input type="submit" value="Update"/>')
res.write('</form>');
res.end();
}
function update(req,res,next) {
if(req.method !== 'PUT') return next();
res.end('update ' + req.body.user.name);
}
var app = express();
app.use(bodyParser())
.use(methodOverride(function(req,res){
if(req.body && typeof req.body === 'object' && 'post_to_put' in req.body){
var method = req.body.post_to_put;
delete req.body.post_to_put;
return method.toUpperCase();
}
}))dai
.use(edit)
.use(update)
.listen(3000,function(){
console.log('start on port 3000');
});
在res.write('<form method="post">');res.write('<input type="hidden" name="post_to_put" value="put"/>');
这两句代码可以看到,form提交时还是使用post,但是在form中增加了一个隐藏输入,名为Post_TO_PUT,值为PUT。服务端接到这个请求后,会做出如下工作:
* 从request中获取body数据(所以body-parser要在该方法之前引用),此时拿到的body数据里面包含POST_TO_PUT,这个值就是实际的PUT
* 从body数据中删除POST_TO_PUT属性
* 返回大写的POST_TO_PUT属性值method.toUpperCase()
,即PUT
利用gzip/deflate压缩response
所有的内容经过压缩
import compression from 'compression';
app.use(compression());
端口监听
app.listen(app.get("port"));
指定根路径时,设置HTTP头信息
app.get('/', function(req, res){
var body = "hello World";
res.setHeader('Content-Type', 'text/plain');
res.setHeader('Content-Length', body.length);
res.end(body);
});
获取网络接口列表
require('os').networkInterfaces();
set方法
set方法用于指定变量的值,如下:
- 设置模板引擎(为系统变量views和view engine指定了变量值。)
app.set('views', './src/views'); //视图存放的目录
app.set('view engine', 'jade'); //网页模板引擎
- 设定port变量(访问端口)
const port = normalizePort(process.env.PORT || '8080');
app.set('port', port);
- 设置静态文件目录
app.use(express.static(path.join(_dirname, ‘public’)));
什么是中间件
中间件(middleware)就是处理HTTP请求的函数,用来完成各种特定的任务,比如:检查用户是否登录、分析数据、以及其他在需要最终将数据发送给用户之前完成的任务,最大的特点就是,一个中间件处理完,再会传递给下一个中间件。
node.js的内置模块http的createServer方法,可以生成一个服务器实例,该实例允许在运行过程中,调用一系列函数(中间件),完成后,根据设置决定是否调用下一个中间件。中间件内部可以使用服务器实例的response对象(第二个参数,即res),以及一个next回调函数(第三个参数,next)。每个中间件都可以对http请求(request对象)做出回应,并且决定是否调用next方法,将request对象再传给下一个中间件。
一个不进行任何操作、只传递request对象的中间件:
function middleWare(req, res, next){
next();
}
上述函数中next()为中间件的回调函数,如果它带有参数,则代表抛出一个错误,其中参数为错误文本;抛出错误以后,后面的中间件将不再执行,直到发现一个错误处理函数为止。
function middleWare(req, res, next){
next("出错了!");
}
use方法
use是express调用中间件的方法,返回的是一个函数,app.all(), app.post(), app.put(),app.delete()和app.get()是app.use的别名。如果在模式参数后面加上问号,表示该参数可选。如下面的who参数。
express.favicon(iconPath):
用来设置网站的图标,参数为图标的路径。如果不指明,则用默认的express图标。可以利用下面的方法进行修改:
app.use(express.favicon(path.join(__dirname, '../public/img/favicon.ico')));
express.bodyParser():
对请求内容进行解析,支持json、application/x-www-form-urlencoded、multipart/form-data格式数据的解析。在express中处理文件上传也是用它,可以给出参数指明上传文件存放的路径,例如:
app.use(express.bodyParser({uploadDir:'./uploads'}));
express.methodOverride():
为了支持put、delete等HTTP方法,不过要客户端配合,包含相应的_method
参数,比如:
<form action='/users/1'>...
<input type="hidden" name="_method" value="put">
</form>
可以对应到:
app.put('/users/:id', users.put)
调试出现的情况
- 当出现
TypeError _guest.getEventDetail is not a function
错误时,有可以是局部作用域定义的变量覆盖了全局变量,使得变量类型为局部定义的数据类型
- 向对象数组里面放对象后,发现数组里面的所有数据与最近对象一样的问题分析
如果没有每578行的将对象重新设置为空就会出现上述问题,这是因为在js里面,对象的赋值是运用的引用地址,当将对象一次一次的放进数组里面时,数组里面的所有的数据存放地址和reservation变量的地址是一样的,所有数据同时指向同一个地址。
常用函数
- Array.join(“,”)可以将数组里面的所有元素转换为以,分割的字符串。
String.split(“,”)可以像字符串以,分割的几部分放到返回的数组里面。
两者的操作是相反的过程