中间件的洋葱模型

原文(保持更新):https://github.com/kenberkeley/redux-simple-tutorial/blob/master/middleware-onion-model.md

本文是 Redux 进阶教程 的拓展阅读

§ Express 的中间件

  1. /** app.js **/
  2. var express = require('express')
  3. var app = express()
  4. app.use(function middleware1(req, res, next) {
  5. console.log('A middleware1 开始')
  6. next()
  7. console.log('B middleware1 结束')
  8. })
  9. app.use(function middleware2(req, res, next) {
  10. console.log('C middleware2 开始')
  11. next()
  12. console.log('D middleware2 结束')
  13. })
  14. app.use(function middleware3(req, res, next) {
  15. console.log('E middleware3 开始')
  16. next()
  17. console.log('F middleware3 结束')
  18. })
  19. app.get('/', function handler(req, res) {
  20. res.send('ok')
  21. console.log('======= G =======')
  22. })
  23. if (module.parent) {
  24. module.exports = app
  25. } else {
  26. app.listen(8080)
  27. }

敲下 node app.js 后,访问 localhost:8080,控制台会输出:

  1. A middleware1 开始
  2. C middleware2 开始
  3. E middleware3 开始
  4. ======= G =======
  5. F middleware3 结束
  6. D middleware2 结束
  7. B middleware1 结束

下面是该请求的示意图:

  1. --------------------------------------
  2. | middleware1 |
  3. | ---------------------------- |
  4. | | middleware2 | |
  5. | | ------------------- | |
  6. | | | middleware3 | | |
  7. | | | | | |
  8. next next next ——————————— | | |
  9. 请求 ——————————————————> | handler | 收尾工作->|
  10. 响应 <————————————————— | G | | | |
  11. | A | C | E ——————————— F | D | B |
  12. | | | | | |
  13. | | ------------------- | |
  14. | ---------------------------- |
  15. --------------------------------------
  16. 顺序 A -> C -> E -> G -> F -> D -> B
  17. \---------------/ \----------/
  18. 请求响应完毕 收尾工作

§ Redux 的中间件(在线演示)

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <script src="//cdn.bootcss.com/redux/3.5.2/redux.min.js"></script>
  5. </head>
  6. <body>
  7. <script>
  8. function middleware1(store) {
  9. return function(next) {
  10. return function(action) {
  11. console.log('A middleware1 开始');
  12. next(action)
  13. console.log('B middleware1 结束');
  14. };
  15. };
  16. }
  17. function middleware2(store) {
  18. return function(next) {
  19. return function(action) {
  20. console.log('C middleware2 开始');
  21. next(action)
  22. console.log('D middleware2 结束');
  23. };
  24. };
  25. }
  26. function middleware3(store) {
  27. return function(next) {
  28. return function(action) {
  29. console.log('E middleware3 开始');
  30. next(action)
  31. console.log('F middleware3 结束');
  32. };
  33. };
  34. }
  35. function reducer(state, action) {
  36. if (action.type === 'MIDDLEWARE_TEST') {
  37. console.log('======= G =======');
  38. }
  39. return {};
  40. }
  41. var store = Redux.createStore(
  42. reducer,
  43. Redux.applyMiddleware(
  44. middleware1,
  45. middleware2,
  46. middleware3
  47. )
  48. );
  49. store.dispatch({ type: 'MIDDLEWARE_TEST' });
  50. </script>
  51. </body>
  52. </html>

控制台输出:

  1. A middleware1 开始
  2. C middleware2 开始
  3. E middleware3 开始
  4. ======= G =======
  5. F middleware3 结束
  6. D middleware2 结束
  7. B middleware1 结束

下面是该请求的示意图:

  1. --------------------------------------
  2. | middleware1 |
  3. | ---------------------------- |
  4. | | middleware2 | |
  5. | | ------------------- | |
  6. | | | middleware3 | | |
  7. | | | | | |
  8. next next next ——————————— | | |
  9. dispatch —————————————> | reducer | 收尾工作->|
  10. nextState <————————————— | G | | | |
  11. | A | C | E ——————————— F | D | B |
  12. | | | | | |
  13. | | ------------------- | |
  14. | ---------------------------- |
  15. --------------------------------------
  16. 顺序 A -> C -> E -> G -> F -> D -> B
  17. \---------------/ \----------/
  18. 更新 state 完毕 收尾工作

§ 总结

Redux 与 Express 的中间件执行流程一致:层层进入,层层冒出,就像从中间穿过洋葱般的体验