express
npm init
npm install ejs body-parser express
http.server
let http = require('http');
const url = require('url');
http.createServer(function (req, res) {
let { query, pathname } = url.parse(req.url, true);
if (pathname == '/signin') {
let str = '';
req.on('data', function (chunk) {
str += chunk;
})
req.on('end', function () {
console.log(str);
})
res.setHeader('Content-Type', 'text/plain;charset=utf8');
return res.end('登录')
}
if (pathname == '/signup') {
res.setHeader('Content-Type', 'text/plain;charset=utf8');
return res.end('注册')
}
}).listen(8080);
const express = require('express');
// 引用express模块, express是个函数\
const app = express(); // express函数执行后返回的是一个http的监听函数,就是http.createServer中的函数
// 测函数上扩展了个listen可以监听端口
app.listen = function(...args){
require('http').createServer(app).listen(...args);
}
// app.listen是基于以前封装的
// app.listen(8080, function(){
// console.log(`start8080`)
// })
express route
const express = require('express');
const app = express();
app.listen(3000, ()=>{
console.log('运行于3000')
});
// app 监听函数上扩展了很多方法,包括get、post、delete、put、RESful风格中的动词
// app.方法名('路径名', fn)
// 从上向下匹配如果匹配到了结束相应
// 路径知道 pathname,没有问好后面的内容
// express重点扩展req和res的属性
app.get('/signin',function(req, res){
res.setHeader('Content-Type', 'text/plain;charset=utf8');
res.end('登录')
});
app.post('/signup',function(req, res){
res.end('注册')
});
app.all('*', function(req, res){
res.end('404');
})
req.attribute
const express = require('express');
const app = express();
app.listen(8080);
//相区分查询一个还是所有
app.get('/user', function (req, res) {
console.log(req.query.id);
console.log(req.url);
console.log(req.path);
console.log(req.headers);// 所有都小写
console.log(req.method);// 都是大写
})
route params
const express = require('express');
const app = express();
app.listen(8080);
// /user?id=1 查一个,/user查所有 路径都是/user
// /user/1 表示查一个 /user查所有
app.get('/user', function (req, res) {
res.end('select all')
});
// id是占位符,必须有但随即
// /user/1/2=>{id:1, name:2} = params;一一对应
app.get('/user/:id/:name', function (req, res) {
res.end('select one'+req.params.id+req.params.name);
});
let url = '/user/1/2/a';
let url2 = '/user/:id/:name/a'; // {id:1, name:2}
// 将url2转化成可以匹配url的正则
let arr = [];
let newReg = url2.replace(/:[^\/]+/g, function(){
arr.push(arguments[0].slice(1));
return '([^\/]+)'
});
let reg = new RegExp(newReg);
let newArr = reg.exec(url);
let result = {};
arr.forEach(function(item, index){
result[item] = newArr[index+1]
});
console.log(result);
const express = require('express');
const app = express();
app.listen(8080);
// 拦截功能,req和res都是同一个
app.param('id', function(req, res, next){
let req.params.id = `你的学号是${req.params.id}`;
next();
});
app.param('name', function(req, res, next){
let req.params.name = `你的姓名是${req.params.name}`;
next();
});
app.get('/user/:id/:name', function (req, res) {
res.header('Content-typy','text/plain;charset=utf-8')
res.end(`${req.params.id}${req.params.name}`);
});
7.中间件middleWare
当我们访问最终目标之前执行的内容
const express = require('express');
const app = express();
app.listen(8080);
//1. 中间件的第一个功能 可以进行权限判断
//2. 可以进行对req和res的扩充
//3. 中间件放在执行路径的上面
//4. 中间件默认情况下都匹配,可以指定匹配什么开头的
app.use('/water', function(req, res, next){// 不调用next不继续往下走
console.log('过滤石头');
req.stone = 'too big';
next('错误');// 这里也会走,不过end只显示过滤石头
});
app.use('/water',function(req, res, next){// 不调用next不继续往下走
console.log('过滤沙子');
req.send = 'too small';
next();
});
// 统一处理
app.use(function(req, res, next){
res.header('Content-type','text/plain;charset=utf-8');
next();
})
app.get('/water/a', function(req, res){// 前面匹配到就生效
console.log(req.stone, req.send)
res.end('water');
})
app.get('/food', function(req, res){
console.log(req.stone, req.send)
res.end('food');
})
app.use(function(err, req, res, next){// 错误中间件有四个参数 fn.length === 4
console.log(err);
})
例子
const express = require('express');
const app = express();
app.listen(8080);
app.use(function(req, res, next){
let t = new Date().getTime();// 访问最初的时间,还要记录end时间
let end = res.end;
res.end = function(...arg){
end.call(res,...arg);
}
next();
});
app.get('water', function(req, res){
for(let i=0;i<1000, i++){
}
res.end('water');// 装饰模式
});
app.get('food', function(req, res){
for(let i=0;i<10000, i++){
}
res.end('food');
})
decorator
function coffee(){
console.log('来一个咖啡');
}
function sweetCoffee(){
coffee();
console.log('加糖')
}
coffee();
sweetCoffee();
next原理
middleWare实现
function app(){
}
// 每次调用use方法,都会将方法存到数组中,默认调用数组的第一项,将next方法传递给数组中函数,如果调用此函数,会继续执行数组中的下一项
app.middleware = [];
app.use = function (cb) {
this.middleware.push(cb);
}
app.use(function(req, res, next){
console.log(1);
next();
});
app.use(function(req, res, next){
console.log(2);
next();
});
app.use(function(req, res, next){
console.log(3);
next();
});
let index = 0;
function next() {
app.middleware[index++](null, null, next);
};
next();
res新加的方法和属性
const express = require('express');
const app = express();
app.listen(8080);
// 不能直接返回对象 res.json();
// 返回thml页面 res.sendFile();返回文件
// res.statusCode res.end = res.sendStatus();
// res.end() res.header(); = res.send();
app.get('/json', function(req, res){
res.json({name:xxx,age: 9});
})
app.get('/', function(req, res){// root不能通过../访问上一级目录
// res.sendFile(__dirname + '/index.html'');
res.sendFile('./index.html',{root: __dirname});// 一般用这个
res.sendFile(require('path').join(__dirname, '..', 'index.html'));// 查找上一级
});
app.get('/status', function(req, res){
res.sendStatus(404);
});
app.use(function(req, res, next){
res.mySend = function(data){
if(typeof data === 'object'){
res.setHeader('Content-Type','application/json;chartset=utf8');
return res.send(JSON.stringify(data));
}
if(typeof data === 'string'){
res.setHeader('Content-Type','text/plain;chartset=utf8');
return res.send(data);
}
if(typeof data === 'number'){
res.statusCode = data;
res.end(require('_http_server').STATUS_CODES[data]);
}
}
next();
})
app.get('/send', function(req, res){
// res.send({name: 'xxx', age: 9});
// res.end(200);
res.mySend();
})