http内置模块,Express和Koa

http内置模块,Node框架Express和Koa

http模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const http = require('http');

// 创建一个web服务器
const server = http.createServer((req, res) => {
res.end("Hello Server");
});

// 启动服务器,并且制定端口号和主机
server.listen(8888, '0.0.0.0', () => {
console.log("服务器启动成功~");
});

如果没有输入端口号,可以通过server.address().port获取
server.listen(() => {
console.log("服务器启动成功~");
console.log(server.address().port)
});

listen函数有三个参数
端口port,可以不穿,系统默认分配
主机host,通常是localhost,ip127.0.0.1,或者0.0.0.0,默认是0.0.0.0
localhost本质上是一个域名会被解析成127.0.0.1
127.0.0.1是回环地址,自己主机发出去的包自己解析,在应用层 => 传输层 => 网络层 => 链路层 => 物理层
在网络层就会被获取,不会经过链路层是物理层
0.0.0.0监听所有IP地址,再根据端口找到不同的应用程序

req

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
request包含请求路径,方法和头等
const server = http.createServer((req, res) => {
console.log(requrl)
console.log(req.ethod)
console.log(req.eaders)
res.end("Hello Server");
});

url
const server = http.createServer((req, res) => {
if(req.url== '/login')
res.end("请登录")
}else if(req.url=='/register'){
res.end("请注册")
}
});

如果访问地址携带参数,利用url模块和qs模块,明文传输方式
const url = require('url')
const qs = require('querystring');
const { pathname, query } = url.parse(req.url);
if (pathname === '/login') {
console.log(qs.parse(query));
const { username, password } = qs.parse(query);
console.log(username, password);
res.end("请求结果~");
}


method
拿到通过post请求发送的json数据,不在地址栏
const server = http.createServer((req, res) => {
console.log(req.method)
if(req.methdos == 'POST'){
//获取body数据
req.setEncoding('utf-8') //设置数据编码 如果是音频和其他文件就是其他编码
req.on('data',(data)=>{
console.log(data.toString()) //字符串类型 {username:"',age:"'}
转换成js对象
const { username, age } = JSON.parse(data.toString())
})
}
});

headers
console.log(req.headers)
contenttype:数据类型
content-length:文件长度
connection:keep-alive保持连接
accept-encoding:告知服务器,客户端支持的文件压缩格式,比如js文件可以使用gzip编码。对应.gz文件
accept:告知服务器科技接收的文件格式
user-agent:客户端相关信息

res

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
response
const server = http.createServer((req, res) => {
1:res.end("响应结果")
2:res.write("响应结果")
res.end()

});

响应状态码
1:需要后续操作
2:OK,成功
3:重定向
4:客户端
5:服务端

状态码设置方式
res.statusCode = 404
res.writeHead(404,{
可以传入header相关的事情
})

设置头方式
1:res.setHeader("content-type", "text/plain")
2:res.writeHead(200, {
"content-type":"text/plain"
})

http发送网络请求

axios在前端使用时,基于xhr,在node端使用时是基于http模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const http = require('http')
http.get('...',(res)=>{
res.on('data',(data)+>{
console.log(data) //结果
})
})

发送post
const req = http.request({
method:'POST',
host:'localhost',
port:8888
},(res)=>{
res.on('data',(data)=>{
console.log('结果')
})
res.on('end',()=>{
console.log('获取到了所有结果')
})
})

req.end() //必须,否则请求停滞

http方式原生的文件上传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
const http = require('http');
const fs = require('fs');
const qs = require('querystring');

const server = http.createServer((req, res) => {
if (req.url === '/upload') {
if (req.method === 'POST') {
//必须,图片编码必须设置为binary
req.setEncoding('binary');

let body = '';
const totalBoundary = req.headers['content-type'].split(';')[1];
const boundary = totalBoundary.split('=')[1];

req.on('data', (data) => {
body += data;
});

req.on('end', () => {
console.log(body);
// 处理body
// 1.获取image/png的位置
const payload = qs.parse(body, "\r\n", ": ");
const type = payload["Content-Type"];

// 2.开始在image/png的位置进行截取
const typeIndex = body.indexOf(type);
const typeLength = type.length;
let imageData = body.substring(typeIndex + typeLength);

// 3.将中间的两个空格去掉
imageData = imageData.replace(/^\s\s*/, '');

// 4.将最后的boundary去掉
imageData = imageData.substring(0, imageData.indexOf(`--${boundary}--`));

fs.writeFile('./foo.png', imageData, 'binary', (err) => {
res.end("文件上传成功~");
})
})
}
}
});

server.listen(8000, () => {
console.log("文件上传服务器开启成功~");
})

Express

基本使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//安装方式 1 脚手架安装
npm install express-generator -g
expres demo
npm install
node bin/www
// 默认启动是loaclhost:3000

// 2自己从0实现
npm install express
// 引入
const express = require('express');
// 返回app
const app = express()
//监听请求路径
app.get('/',(req,res,next)=>{
res.end('hello get')
})
app.post('/',(req,res,next)=>{
res.end('hello post')
})

app.listen(5000,()=>{
console.log('开启')
})

express的中间件,中间件就是回调函数,接受req,res,next,next是执行下一个中间件的方法,express本质上是中间件的调用

中间件中可以执行任何代码,更改请求和响应对象,结束请求,响应周期,返回数据,调用栈中的下一个中间件

如果没有res.end就需要next传递给下一个中间件,否则请求会被挂起,不会结束

express提供了两种方式将中间件应用与程序中,app/router.use和app/router.methods

可以是app,也可以是router,methods是指常用的请求方式app.get或者app.post

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
中间件类型1//最普通的中间件
app.use((req,res,next)=>{
console.log('注册了第一个普通中间件')
})
只会执行一个中间件
app.use((req,res,next)=>{
console.log('注册了第一个普通中间件')
res.end()
// 想要让第二个中间件执行得
next()
})

app.use((req,res,next)=>{
console.log('注册了第二个普通中间件')
res.end() // 报错 不能在end之后再end,end只能有一个
})

中间件类型2//path匹配中间件
app.use(path,callback)
app.use('/home',(req,res,next)=>{
console.log('匹配到了/home')
res.end('end')
}
如果有相同的path匹配中间件,永远只会调用第一个中间件,除非使用next

中间件类型3//path和method匹配中间件
app.get('/home',(req.res,next)=>{

})

中间件类型4//注册多个中间件
app.get('/home',(req,res,next)=>{

},(req,res,next)=>{

},(req,res,next)=>{

})

//使用express解析req.body很轻松 解析json
app.use(express.json())

// true是使用qs解析,false那么就是使用node中的queryString进行解析 解析urlencoded
app.use(express.urlencoded({extended:true}))

// 解析formdata
npm install multer
const upload = require('multer')
app.use(multer.any())
// 上穿文件 设置上传路径
const multer = multer({
dest:'./uploads/' // 上传文件保存位置,
})
const path = require('path'
const storage = muliter.diskStorge({
destintion: (req,res,cb)=>{
cb(null,'./uploads/')
}//目的地,
filename: (req,res,cb)=>{
cb(null, Date.now() + path.extname(file.originalname))
}
})
upload.single 上传单个文件 upload.array 上传多个文件 可以传递一个key值表示具体处理哪个数据
app.post('/upload',upload.single('') ,(req,res,next)=>{
console.log(req.files)
res.end('上传成功')
})
// 默认没有后缀名

中间件用法

json解析

express内置一些request解析的中间件 ,当客户端发送请求post请求时,会把数据放到req.body中

客户端可以通过json也可以通过form表单的方式传递

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
post 发送username和age

自己写的
// app.use((req, res, next) => {
// if (req.headers["content-type"] === 'application/json') {
// req.on('data', (data) => {
// const info = JSON.parse(data.toString());
// req.body = info;
// })

// req.on('end', () => {
// next();
// })
// } else {
// next();
// }
// })

使用express
// 使用express提供给我们的body解析
// body-parser: express3.x 内置express框架
// body-parser: express4.x 被分离出去
// body-parser类似功能: express4.16.x 内置成函数
app.use(express.json()); //传送数据为json格式时 application/json
// extended
// true: 那么对urlencoded进行解析时, 它使用的是第三方库: qs
// false: 那么对urlencoded进行解析时, 它使用的是Node内置模块: querystring
app.use(express.urlencoded({extended: true}));//传送数据解析application/x-www-form-urlencoded
后续可直接通过打印req.body方式获取传送数据
app.post('/login', (req, res, next) => {
console.log(req.body);
res.end("Coderwhy, Welcome Back~");
});

app.post('/products', (req, res, next) => {
console.log(req.body);
res.end("Upload Product Info Success~");
});

app.listen(8000, () => {
console.log("express初体验服务器启动成功~");
});

formdata解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
npm install multer

const express = require('express');
const multer = require('multer');

const app = express();

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

const upload = multer();

app.use(upload.any());

app.post('/login', (req, res, next) => {
console.log(req.body);
res.end("用户登录成功~")
});

app.listen(8000, () => {
console.log("form-data解析服务器启动成功~")
});

formdata上传文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
const path = require('path');

const express = require('express');
const multer = require('multer');

const app = express();

app.use(express.json());
app.use(express.urlencoded({ extended: true }));

//自定义的文件信息
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, './uploads/');
},
filename: (req, file, cb) => {
cb(null, Date.now() + path.extname(file.originalname));
}
})

const upload = multer({
// dest: './uploads/' //文件存储路径
storage //自定义文件存储信息
});

app.post('/login', upload.any(), (req, res, next) => {
console.log(req.body);
res.end("用户登录成功~")
});

上传单个文件
app.post('/upload', upload.single('file'), (req, res, next) => {
console.log(req.files);
res.end("文件上传成功~");
});

上传多个文件
app.post('/upload', upload.array('file'), (req, res, next) => {
console.log(req.files);
res.end("文件上传成功~");
});

app.listen(8000, () => {
console.log("form-data解析服务器启动成功~")
});

保存日志信息

使用express开发的第三方中间件,morgan,需要单独安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const fs = require('fs');

const express = require('express');
const morgan = require('morgan');

const app = express();

const writerStream = fs.createWriteStream('./logs/access.log', {
flags: "a+"
})
//combined是保存的日志格式,
app.use(morgan("combined", {stream: writerStream}));

app.get('/home', (req, res, next) => {
res.end("Hello World");
})

app.listen(8000, () => {
console.log("express初体验服务器启动成功~");
});

request参数解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const express = require('express');

const app = express();

app.get('/products/:id/:name', (req, res, next) => {
console.log(req.params);
// req.params => 在数据库中查询真实的商品数据
res.end("商品的详情数据~");
})

app.get('/login', (req, res, next) => {
console.log(req.query);
res.end("用户登录成功~");
})

app.listen(8000, () => {
console.log("普通中间件服务器启动成功~");
});


response响应结果解析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
const express = require('express');
const router = require('./routers/users');

const app = express();

app.get('/products/:id/:name', (req, res, next) => {
console.log(req.params);
// req.params => 在数据库中查询真实的商品数据
res.end("商品的详情数据~");
})

app.get('/login', (req, res, next) => {
console.log(req.query);

// 设置响应吗
res.status(204);

// res.type("application/json");
// res.end(JSON.stringify({name: "why", age: 18}));
// res.json({name: "why", age: 18})
// 设置内容
res.json(["abc", "cba", "abc"]);
});

/**
* 举个例子:
* 请求所有的用户信息: get /users
* 请求所有的某个用户信息: get /users/:id
* 请求所有的某个用户信息: post /users body {username: passwod:}
* 请求所有的某个用户信息: delete /users/:id
* 请求所有的某个用户信息: patch /users/:id {nickname: }
*/

app.listen(8000, () => {
console.log("普通中间件服务器启动成功~");
});


路由的使用

如果将所有代码放在app中,那么app会越来越复杂,可以使用express.Router创建一个路由处理程序,一个路由实例拥有完整的中间件和路由系统,因此也被称为迷你应用程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
const express = require('express');
const userRouter = require('./routers/users');
const productRouter = require('./routers/products');

const app = express();

app.use("/users", userRouter);
app.use("/products", productRouter);

app.listen(8000, () => {
console.log("路由服务器启动成功~");
});

routers/users
/**
* 举个例子:
* 请求所有的用户信息: get /users
* 请求所有的某个用户信息: get /users/:id
* 请求所有的某个用户信息: post /users body {username: passwod:}
* 请求所有的某个用户信息: delete /users/:id
* 请求所有的某个用户信息: patch /users/:id {nickname: }
*/

const express = require('express');

const router = express.Router();

router.get('/', (req, res, next) => {
res.json(["why", "kobe", "lilei"]);
});

router.get('/:id', (req, res, next) => {
res.json(`${req.params.id}用户的信息`);
});

router.post('/', (req, res, next) => {
res.json("create user success~");
});

module.exports = router;

静态服务器

express提供了部署静态资源的方法

1
2
3
4
5
6
7
8
9
10
const express = require('express');

const app = express();

app.use(express.static('./build')); //.build中是打包后的文件 npm run build

app.listen(8000, () => {
console.log("路由服务器启动成功~");
});

express的错误处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
const express = require('express');

const app = express();

const USERNAME_DOES_NOT_EXISTS = "USERNAME_DOES_NOT_EXISTS";
const USERNAME_ALREADY_EXISTS = "USERNAME_ALREADY_EXISTS";

app.post('/login', (req, res, next) => {
// 加入在数据中查询用户名时, 发现不存在
const isLogin = false;
if (isLogin) {
res.json("user login success~");
} else {
// res.type(400);
// res.json("username does not exists~")
next(new Error(USERNAME_DOES_NOT_EXISTS));
}
})

app.post('/register', (req, res, next) => {
// 加入在数据中查询用户名时, 发现不存在
const isExists = true;
if (!isExists) {
res.json("user register success~");
} else {
// res.type(400);
// res.json("username already exists~")
next(new Error(USERNAME_ALREADY_EXISTS));
}
});

app.use((err, req, res, next) => {
let status = 400;
let message = "";
console.log(err.message);

switch(err.message) {
case USERNAME_DOES_NOT_EXISTS:
message = "username does not exists~";
break;
case USERNAME_ALREADY_EXISTS:
message = "USERNAME_ALREADY_EXISTS~"
break;
default:
message = "NOT FOUND~"
}

res.status(status);
res.json({
errCode: status,
errMessage: message
})
})

app.listen(8000, () => {
console.log("路由服务器启动成功~");
});

更多细节察看expressjs.com.cn

部分原理

调用express创建的是什么

ap.listen如何结合原生启动服务器

listen在createApplication中表面上看不出来,实际上在mixin(app。proto,false)中

调用了原生的http创建服务器启动监听

loading……

app.use发生了什么

用户发送网络请求如何执行中间件回调

next为什么会执行下一个中间件

Koa

koa自称是node.js的下一代框架,koa是和express同一个团队开发的框架

koa旨在为web应用程序和api提供更小,更丰富和强大的能力

相对于express具有更强大的异步处理能力

koa的核心代码只有一千多行,很清凉

我们可以根据需要考虑安装中间件

1
2
3
4
5
6
7
8
9
10
11
12
const Koa = require('koa');

const app = new Koa();
//ctx = context 上下文对象 包含request和response
app.use((ctx, next) => {
ctx.response.body = "Hello World";
});

app.listen(8000, () => {
console.log("koa初体验服务器启动成功~");
});

注册中间件

koa并没有提供methods,path和连续注册的方式注册中间件

只能通过app.use(()=>{})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const Koa = require('koa');

const app = new Koa();

// use注册中间件
app.use((ctx, next) => {
if (ctx.request.url === '/login') {
if (ctx.request.method === 'GET') {
console.log("来到了这里~");
ctx.response.body = "Login Success~";
}
} else {
ctx.response.body = "other request~";
}
});

// 没有提供下面的注册方式
// methods方式: app.get()/.post
// path方式: app.use('/home', (ctx, next) => {})
// 连续注册: app.use((ctx, next) => {
// }, (ctx, next) => {
// })

app.listen(8000, () => {
console.log("koa初体验服务器启动成功~");
});

路由的使用

需要安装第三方库 koa-router

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
const Koa = require('koa');

const userRouter = require('./router/user');

const app = new Koa();

app.use((ctx, next) => {
// ctx.response.body = "Hello World";
next();
});

app.use(userRouter.routes());
app.use(userRouter.allowedMethods()); //如果访问了错误的地址和方式

app.listen(8000, () => {
console.log("koa路由服务器启动成功~");
});

//routers
const Router = require('koa-router');

const router = new Router({prefix: "/users"});

router.get('/', (ctx, next) => {
ctx.response.body = "User Lists~";
});

router.put('/', (ctx, next) => {
ctx.response.body = "put request~";
});


module.exports = router;

参数解析query,params

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const Koa = require('koa');

const app = new Koa();
const Router = require('koa-router');

const userRouter = new Router({prefix: '/users'});

userRouter.get('/:id', (ctx, next) => {
console.log(ctx.request.params);
console.log(ctx.request.query);
})

// app.use((ctx, next) => {
// console.log(ctx.request.url);
// console.log(ctx.request.query);
// console.log(ctx.request.params);
// ctx.response.body = "Hello World";
// });

app.use(userRouter.routes());

app.listen(8000, () => {
console.log("参数处理服务器启动成功~");
});

参数解析urlenclded和formdata

npm install koa-bodyparser koa-multer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const Koa = require('koa');
const bodyParser = require('koa-bodyparser'); //json,urlencoded
const multer = require('koa-multer'); //form-data
const Router = require('koa-router');

const app = new Koa();

const upload = multer();

app.use(bodyParser());
app.use(upload.any());

app.use((ctx, next) => {
console.log(ctx.request.body);
console.log(ctx.req.body); //multer塞进去的
ctx.response.body = "Hello World";
});

app.listen(8000, () => {
console.log("koa初体验服务器启动成功~");
});

文件上传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const Koa = require('koa');
const Router = require('koa-router');
const multer = require('koa-multer');

const app = new Koa();
const uploadRouter = new Router({prefix: '/upload'});

// const storage = multer.diskStorage({
// destination,
// filename,
// })

const upload = multer({
dest: './uploads/'
});

uploadRouter.post('/avatar', upload.single('avatar'), (ctx, next) => {
console.log(ctx.req.file);
ctx.response.body = "上传头像成功~";
});

app.use(uploadRouter.routes());

app.listen(8000, () => {
console.log("koa初体验服务器启动成功~");
});

koa响应内容

body将相应主体分为

string

Buffer

Stream

Object/Array

null

如果response.status未设置,koa自动设置状态为200或者204 //有内容200,没内容返回null和204

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const Koa = require('koa');

const app = new Koa();

app.use((ctx, next) => {
// ctx.request.query
// ctx.query

// 设置内容
// ctx.response.body
// ctx.response.body = "Hello world~"
// ctx.response.body = {
// name: "coderwhy",
// age: 18,
// avatar_url: "https://abc.png"
// };
// 设置状态码
// ctx.response.status = 400;
// ctx.response.body = ["abc", "cba", "nba"];

// ctx.response.body = "Hello World~";
ctx.status = 404;
ctx.body = "Hello Koa~";
});

app.listen(8000, () => {
console.log("koa初体验服务器启动成功~");
});

部署静态资源

npm Install koa-static

1
2
3
4
5
6
7
8
9
10
11
const Koa = require('koa');
const staticAssets = require('koa-static');

const app = new Koa();

app.use(staticAssets('./build'));

app.listen(8000, () => {
console.log("koa初体验服务器启动成功~");
});

错误处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
const Koa = require('koa');

const app = new Koa();

app.use((ctx, next) => {
const isLogin = false;
if (!isLogin) {
ctx.app.emit('error', new Error("您还没有登录~"), ctx);
}
});

app.on('error', (err, ctx) => {
ctx.status = 401;
ctx.body = err.message;
})

app.listen(8000, () => {
console.log("koa初体验服务器启动成功~");
});

express和koa的区别

express比较完整,koa比较自由简洁只包含核心功能,我们需要自己安装使用

两者核心都是中间件

express同步数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const express = require('express');

const app = express();

const middleware1 = (req, res, next) => {
req.message = "aaa";
next();
res.end(req.message);
}

const middleware2 = (req, res, next) => {
req.message += "bbb";
next();
}

const middleware3 = (req, res, next) => {
req.message += "ccc";
}

app.use(middleware1, middleware2, middleware3);

app.listen(8000, () => {
console.log("服务器启动成功~");
})

express异步数据

express处理异步数据非常麻烦,只能单独抽离函数await

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const express = require('express');
const axios = require('axios');

const app = express();

const middleware1 = async (req, res, next) => {
req.message = "aaa";
await next();
res.end(req.message);
}

const middleware2 = async (req, res, next) => {
req.message += "bbb";
await next();
}

const middleware3 = async (req, res, next) => {
const result = await axios.get('http://123.207.32.32:9001/lyric?id=167876');
req.message += result.data.lrc.lyric;
}

app.use(middleware1, middleware2, middleware3);

app.listen(8000, () => {
console.log("服务器启动成功~");
})

koa同步数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const Koa = require('koa');

const app = new Koa();

const middleware1 = (ctx, next) => {
ctx.message = "aaa";
next();
ctx.body = ctx.message;
}

const middleware2 = (ctx, next) => {
ctx.message += "bbb";
next();
}

const middleware3 = (ctx, next) => {
ctx.message += "ccc";
}

app.use(middleware1);
app.use(middleware2);
app.use(middleware3);

app.listen(8000, () => {
console.log("服务器启动成功~");
})

koa异步数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const Koa = require('koa');
const axios = require('axios');

const app = new Koa();

const middleware1 = async (ctx, next) => {
ctx.message = "aaa";
await next();
next();
ctx.body = ctx.message;
}

const middleware2 = async (ctx, next) => {
ctx.message += "bbb";
await next();
}

const middleware3 = async (ctx, next) => {
const result = await axios.get('http://123.207.32.32:9001/lyric?id=167876');
ctx.message += result.data.lrc.lyric;
}

app.use(middleware1);
app.use(middleware2);
app.use(middleware3);

app.listen(8000, () => {
console.log("服务器启动成功~");
})

洋葱模型

……

学无止境,结束意味着新的开始

loading……