洋葱模型(栈, 先进后出)

洋葱的表皮我们可以思考为中间件

  • 从外向内的过程是一个关键词 next();
  • 而从内向外则是每个中间件执行完毕后,进入下一层中间件,一直到最后一层。

中间件: 后端服务请求和相应中间执行的函数

Express VS KOA

Express KOA
中间件 内置很多中间件 轻量, @koa/router需要单独引入
异步 基于callback处理 基于await/async
洋葱模型执行中间件 非严格 严格遵循
优势 功能全,发展时间长 未来的趋势

原因: 基于nodejs的版本不同

Express 执行中间件

  1. const express = require('express')
  2. const app = express()
  3. app.use((req, res, next) => {
  4. console.log('1');
  5. next();
  6. console.log('1 end');
  7. })
  8. app.use((req, res, next) => {
  9. console.log('2');
  10. next();
  11. console.log('2 end');
  12. })
  13. app.use((req, res, next) => {
  14. console.log('3');
  15. next();
  16. console.log('3 end');
  17. })
  18. app.get('/', function (req, res) {
  19. res.send('Hello World')
  20. })
  21. app.listen(3000, () => console.log('listen 3000'))
  22. // listen 3000
  23. // 1
  24. // 2
  25. // 3
  26. // 3 end
  27. // 2 end
  28. // 1 end

koa 执行中间件

  1. const Koa = require('koa');
  2. const app = new Koa();
  3. app.use((ctx, next) => {
  4. console.log('1');
  5. next();
  6. console.log('1 end');
  7. })
  8. app.use((ctx, next) => {
  9. console.log('2');
  10. next();
  11. console.log('2 end');
  12. })
  13. app.use((ctx, next) => {
  14. console.log('3');
  15. next();
  16. console.log('3 end');
  17. })
  18. app.use(ctx => {
  19. ctx.body = 'Hello World';
  20. })
  21. app.listen(3000, () => console.log('listen 3000'))
  22. // listen 3000
  23. // 1
  24. // 2
  25. // 3
  26. // 3 end
  27. // 2 end
  28. // 1 end

Express 执行异步中间件

  1. const express = require('express')
  2. const app = express()
  3. app.use(async (req, res, next) => {
  4. console.log('1');
  5. await next();
  6. console.log('1 end');
  7. })
  8. app.use(async (req, res, next) => {
  9. console.log('2');
  10. await next();
  11. await new Promise((resolve, reject) => {
  12. setTimeout(() => {
  13. console.log('wait');
  14. resolve();
  15. }, 1000)
  16. })
  17. console.log('2 end');
  18. })
  19. app.use(async (req, res, next) => {
  20. console.log('3');
  21. await next();
  22. console.log('3 end');
  23. })
  24. app.get('/', function (req, res) {
  25. res.send('Hello World')
  26. })
  27. app.listen(3000, () => console.log('listen 3000'))
  28. // 1
  29. // 2
  30. // 3
  31. // 3 end
  32. // 1 end
  33. // wait
  34. // 2 end

koa 执行异步中间件

  1. const Koa = require('koa');
  2. const app = new Koa();
  3. app.use(async (ctx, next) => {
  4. console.log('1');
  5. await next();
  6. console.log('1 end');
  7. })
  8. app.use(async (ctx, next) => {
  9. console.log('2');
  10. await next();
  11. await new Promise((resolve, reject) => {
  12. setTimeout(() => {
  13. console.log('wait');
  14. resolve();
  15. }, 1000)
  16. })
  17. console.log('2 end');
  18. })
  19. app.use(async (ctx, next) => {
  20. console.log('3');
  21. await next();
  22. console.log('3 end');
  23. })
  24. app.use(ctx => {
  25. ctx.body = 'Hello World';
  26. })
  27. app.listen(3000, () => console.log('listen 3000'))
  28. // listen 3000
  29. // 1
  30. // 2
  31. // 3
  32. // 3 end
  33. // wait
  34. // 2 end
  35. // 1 end

Egg.js(KOA 框架基础上的最佳实践)